我有一个包含{a,b,c,at,h,c,bt}
的列表,我想把它分成List<List<string>>{{a,b,c},{at,h,c},{bt}};
如果特定字符串包含"t"
,我需要在那一行中断,如何在linq中实现这一点?
嗯,有一种非常糟糕的方法:
int tCounter = 0;
var groups = sequence.GroupBy(x => x.Contains("t") ? ++tCounter : tCounter)
.Select(group => group.ToList())
.ToList();
int tCounter = 0;
var groups = sequence.GroupBy(x => x.Contains("t") ? ++tCounter : tCounter,
(count, group) => group.ToList())
.ToList();
这依赖于GroupBy
子句中的副作用,这是一个非常糟糕的想法。LINQ是围绕函数式理念设计的,查询不应该有副作用。你应该在使用查询的代码中放置副作用,而不是在查询本身中放置副作用。这样做可以工作,但我不建议。
这里有一个简短但完整的演示,只是为了证明它确实可以工作:
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
static void Main(string[] args)
{
var input = new List<string>{"a","b","c","at","h","c","bt"};
int tCounter = 0;
var groups = input.GroupBy(x => x.Contains("t") ? ++tCounter : tCounter)
.Select(group => group.ToList())
.ToList();
foreach (var list in groups)
{
Console.WriteLine(string.Join(", ", list));
}
}
}
输出:
a, b, c
at, h, c
bt
foldl
只是LINQ的标准Aggregate
方法的等价物。 - LukeH您需要的正是内置扩展方法Aggregate。
var source = new List<string> { "a", "b", "c", "at", "h", "c", "bt" };
var result = source.Aggregate(new List<List<string>>(), (list, s) =>
{
if (list.Count == 0 || s.Contains('t')) list.Add(new List<string>());
list.Last().Add(s);
return list;
});
result
是List<List<string>>
。
我认为使用内置的Linq方法无法完成(实际上,可以...请参见其他答案),但是您可以轻松地创建自己的扩展方法来实现此目的:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, Func<T, bool> isSeparator)
{
List<T> list = new List<T>();
foreach(T item in source)
{
if (isSeparator(item))
{
if (list.Count > 0)
{
yield return list;
list = new List<T>();
}
}
list.Add(item);
}
if (list.Count > 0)
{
yield return list;
}
}
然后按照以下方式使用:
var list = new[] { "a", "b", "c", "at", "h", "c", "bt" };
var result = list.Split(s => s.Contains("t"));
这个问题对我来说并不是显然需要使用LINQ。如果你只是想练习一下使用LINQ,那就另当别论了。但是,以下是我如何解决它的方法(使用普通的循环):
List<List<string>> list = new List<List<string>>();
List<string> sublist = new List<string>();
foreach (string element in originalList)
{
if (element.Contains("t"))
{
list.Add(sublist);
sublist = new List<string>();
}
sublist.Add(element);
}
list.Add(sublist);
别误会,我比任何人都更喜欢使用LINQ。 :)