7

我有一串用空格分隔的单词。如何根据单词长度将字符串拆分为单词列表?

例子

输入:

" aa aaa aaaa bb bbb bbbb cc ccc cccc cccc bbb bb aa "

输出 :

List 1 = { aa, bb, cc}
List 2 = { aaa, bbb, ccc}
List 3 = { aaaa, bbbb, cccc}
4

5 回答 5

10

您可以使用它Where来查找与谓词匹配的元素(在这种情况下,具有正确的长度):

string[] words = input.Split();

List<string> twos = words.Where(s => s.Length == 2).ToList();
List<string> threes = words.Where(s => s.Length == 3).ToList();
List<string> fours = words.Where(s => s.Length == 4).ToList();

或者,您可以使用GroupBy一次查找所有组:

var groups = words.GroupBy(s => s.Length);

您还可以使用ToLookup以便您可以轻松索引以查找特定长度的所有单词:

var lookup = words.ToLookup(s => s.Length);
foreach (var word in lookup[3])
{
    Console.WriteLine(word);
}

结果:

啊啊啊
bbb
ccc

在线查看它:ideone


在您的更新中,您似乎想要删除空字符串和重复的单词。您可以通过 using 执行前者,StringSplitOptions.RemoveEmptyEntries后者通过 using 执行Distinct

var words = input.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
                 .Distinct();
var lookup = words.ToLookup(s => s.Length);

输出:

aa, bb, cc
aaa, bbb, ccc
aaaa, bbbb, cccc

在线查看它:ideone

于 2012-07-07T20:21:53.113 回答
6

编辑:我很高兴我的原始答案帮助 OP 解决了他们的问题。然而,在稍微思考了这个问题之后,我已经对其进行了调整(我强烈建议不要使用我以前的解决方案,我在帖子末尾留下了这个解决方案)。

一个简单的方法

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);

解释

首先,我们修剪输入以避免来自外部空间的空元素。然后,我们将字符串拆分为一个数组。如果单词之间出现多个空格,则需要使用StringSplitOptionsas in Mark's answer

在调用Distinct只包含每个单词一次之后,我们现在将wordsfrom 转换IEnumerable<string>Lookup<int, string>,其中单词的长度由 key 表示,(int)单词本身存储在 value 中(string)

等等,这怎么可能?我们不是每个键都有多个单词吗?当然,但这正是Lookup课程的用途:

Lookup<TKey, TElement>表示一组键,每个键映射到一个或多个值。ALookup<TKey, TElement>类似于Dictionary<TKey, TValue>. 不同之处在于 Dictionary 将键映射到单个值,而 Lookup 将键映射到值的集合

Lookup您可以通过调用ToLookup实现 的对象来创建 a 的实例IEnumerable<T>


注意
没有用于创建 Lookup 的新实例的公共构造函数。此外,Lookup 对象是不可变的,也就是说,您不能在 Lookup 创建后添加或删除元素或键。

word => word.LengthKeySelector lambda:它定义了我们要按单词的长度来索引(或分组,如果你愿意Lookup的话)。

用法

将所有单词写入控制台

(类似于问题最初要求的输出)

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

输出

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

将一定长度的所有单词放在一个List

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

按键排序

(请注意,这些将返回IOrderedEnumerable<T>,因此不再可以通过密钥访问)

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

原始答案 - 请不要这样做(性能不佳,代码混乱):

string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc cccc bbb bb aa ";
Dictionary<int, string[]> results = new Dictionary<int, string[]>();
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());
}
于 2012-07-07T21:11:29.537 回答
3

首先,让我们声明一个可以保存长度以及单词列表的类

public class WordList
{
    public int WordLength { get; set; }
    public List<string> Words { get; set; }
}

现在,我们可以用

string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc ";
string[] words = input.Trim().Split();
List<WordList> list = words
    .GroupBy(w => w.Length)
    .OrderBy(group => group.Key)
    .Select(group => new WordList { 
        WordLength = group.Key, 
        Words = group.Distinct().OrderBy(s => s).ToList() 
    })
    .ToList();

这些列表分别按长度和 aphabetally 排序。


结果

在此处输入图像描述

例如

list[2].WordLength ==> 4
list[2].Words[1] ==> "bbbb"

更新

如果需要,您可以立即处理结果,而不是将其放入数据结构中

string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc ";

var query = input
    .Trim()
    .Split()
    .GroupBy(w => w.Length)
    .OrderBy(group => group.Key);

// Process the result here
foreach (var group in query) {
    // group.Key ==> length of words
    foreach (string word in group.Distinct().OrderBy(w => w)) {
       ...
    }
}
于 2012-07-07T20:40:44.497 回答
1

您可以使用 Linq GroupBy

编辑 现在我应用了 Linq 来生成你想要输出的字符串列表。

edit2 应用了多个输入,单个输出,就像在编辑的问题中一样。这只是 Linq 中的一个 Distinct 调用

string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc ";

var list = input.Split(' ');

var grouped = list.GroupBy(s => s.Length);

foreach (var elem in grouped)
{
    string header = "List " + elem.Key + ": ";
    // var line = elem.Aggregate((workingSentence, next) => next + ", " + workingSentence);

    // if you want single items, use this
    var line = elem.Distinct().Aggregate((workingSentence, next) => next + ", " + workingSentence);
    string full = header + " " + line;
    Console.WriteLine(full);
}


// output: please note the last blank in the input string! this generates the 0 list
List 0:  ,
List 2:  cc, bb, aa
List 3:  ccc, bbb, aaa
List 4:  cccc, bbbb, aaaa
于 2012-07-07T20:42:48.657 回答
0

有点冗长的解决方案,但确实在字典中得到了结果

class Program
    {
        public static void Main()
        {
            Print();
            Console.ReadKey();
        }

        private static void Print()
        {
            GetListOfWordsByLength();

            foreach (var list in WordSortedDictionary)
            {
                list.Value.ForEach(i => { Console.Write(i + ","); });
                Console.WriteLine();
            }
        }

        private static void GetListOfWordsByLength()
        {
            string input = " aa aaa aaaa bb bbb bbbb cc ccc cccc ";

            string[] inputSplitted = input.Split(' ');

            inputSplitted.ToList().ForEach(AddToList);
        }

        static readonly SortedDictionary<int, List<string>> WordSortedDictionary = new SortedDictionary<int, List<string>>();

        private static void AddToList(string s)
        {
            if (s.Length > 0)
            {
                if (WordSortedDictionary.ContainsKey(s.Length))
                {
                    List<string> list = WordSortedDictionary[s.Length];
                    list.Add(s);
                }
                else
                {
                    WordSortedDictionary.Add(s.Length, new List<string> {s});
                }
            }
        }
    }
于 2012-07-07T21:13:39.733 回答