Splitting string into words length-based lists c#

后端 未结 5 1782
春和景丽
春和景丽 2021-01-12 14:17

I have a string of words separated by spaces. How to split the string into lists of words based on the words length?

Example

inpu

5条回答
  •  死守一世寂寞
    2021-01-12 14:46

    Edit: I'm glad my original answer helped the OP solve their problem. However, after pondering the problem a bit, I've adapted it (and I strongly advise against my former solution, which I have left at the end of the post).

    A simple approach

    string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc cccc bbb bb aa ";
    var words = input.Trim().Split().Distinct();
    var lookup = words.ToLookup(word => word.Length);
    

    Explanation

    First, we trim the input to avoid empty elements from the outer spaces. Then, we split the string into an array. If multiple spaces occur in between the words, you'd need to use StringSplitOptions as as in Mark's answer.

    After calling Distinct to only include each word once, we now convert words from IEnumerable to Lookup, where the words' length is represented by the key (int) and the words themselves are stored in the value (string).

    Hang on, how is that even possible? Don't we have multiple words for each key? Sure, but that's exactly what the Lookup class is there for:

    Lookup represents a collection of keys each mapped to one or more values. A Lookup resembles a Dictionary. The difference is that a Dictionary maps keys to single values, whereas a Lookup maps keys to collections of values.

    You can create an instance of a Lookup by calling ToLookup on an object that implements IEnumerable.


    Note
    There is no public constructor to create a new instance of a Lookup. Additionally, Lookup objects are immutable, that is, you cannot add or remove elements or keys from a Lookup after it has been created.

    word => word.Length is the KeySelector lambda: it defines that we want to index (or group, if you will) the Lookup by the Length of the words.

    Usage

    Write all the words to the console

    (similar to the question's originally requested output)

    foreach (var grouping in lookup)
    {
        Console.WriteLine("{0}: {1}", grouping.Key, string.Join(", ", grouping));
    }
    

    Output

    2: aa, bb, cc
    3: aaa, bbb, ccc
    4: aaaa, bbbb, cccc
    

    Put all words of a certain length in a List

    List list3 = lookup[3].ToList();
    

    Order by key

    (note that these will return IOrderedEnumerable, so access by key is no longer possible)

    var orderedAscending = lookup.OrderBy(grouping => grouping.Key);
    var orderedDescending = lookup.OrderByDescending(grouping => grouping.Key);
    

    Original answer - please don't do this (bad performance, code clutter):

    string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc cccc bbb bb aa ";
    Dictionary results = new Dictionary();
    var grouped = input.Trim().Split().Distinct().GroupBy(s => s.Length)
        .OrderBy(g => g.Key); // or: OrderByDescending(g => g.Key);
    foreach (var grouping in grouped)
    {
        results.Add(grouping.Key, grouping.ToArray());
    }
    

提交回复
热议问题