【发布时间】:2012-07-07 20:45:32
【问题描述】:
我有一串用空格分隔的单词。如何根据单词长度将字符串拆分成单词列表?
示例
输入:
" 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}
【问题讨论】:
我有一串用空格分隔的单词。如何根据单词长度将字符串拆分成单词列表?
示例
输入:
" 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}
【问题讨论】:
您可以使用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
在您的更新中,您似乎想要删除空字符串和重复的单词。前者可以使用StringSplitOptions.RemoveEmptyEntries,后者可以使用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
【讨论】:
words 三次。对于一个小的input,这可能无关紧要。
首先,让我们声明一个可以保存长度和单词列表的类
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();
列表分别按长度和字母顺序排序。
结果
例如
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)) {
...
}
}
【讨论】:
words.GroupBy(... 替换为input.Trim().Split().GroupBy(...。
var query = input ... 中执行。
你可以使用 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
【讨论】:
编辑:我很高兴我的原始答案帮助 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);
首先,我们修剪输入以避免来自外部空间的空元素。然后,我们将字符串拆分为一个数组。如果单词之间有多个空格,您需要像Mark's answer 一样使用StringSplitOptions。
在调用Distinct 使每个单词只包含一次之后,我们现在将words 从IEnumerable<string> 转换为Lookup<int, string>,其中单词的长度由键(int) 表示,单词本身存储在值(string)。
等等,这怎么可能?我们不是每个键都有多个单词吗?当然,但这正是 Lookup 类的用途:
Lookup<TKey, TElement>表示一组键,每个键映射到一个或多个 价值观。Lookup<TKey, TElement>类似于Dictionary<TKey, TValue>。不同之处在于 Dictionary 将键映射到单个值,而 Lookup 将键映射到值集合。您可以通过在对象上调用
ToLookup来创建Lookup的实例 实现IEnumerable<T>。
注意
没有公共构造函数来创建 Lookup 的新实例。 此外,查找对象是不可变的,也就是说,您不能添加或 在创建后从查找中删除元素或键。
word => word.Length 是 KeySelector 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());
}
【讨论】:
words.Distinct().GroupBy(s => s.Length); 正在为我工作。它不是给你预期的结果吗?
有点冗长的解决方案,但确实会在字典中得到结果
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});
}
}
}
}
【讨论】: