C# Linq中的按元素分组
假设我们有以下数组C# Linq中的按元素分组,c#,linq,group-by,C#,Linq,Group By,假设我们有以下数组 var arr = new string[] {"foo","bar","jar","\r","a","b,"c","\r","x","y","z","\r"); 同时忽略这是字符串的事实,所以请不要使用字符串破解解决方案 我想按序列中的每个“\r”对这些元素进行分组。 也就是说,我想要一个带有“foo”、“bar”、“jar”的数组/枚举,另一个带有“a”、“b”、“c”等 ienumerable扩展中是否有任何东西可以让我这样做,或者我必须在这里按方法滚动我自己的组?为
var arr = new string[] {"foo","bar","jar","\r","a","b,"c","\r","x","y","z","\r");
同时忽略这是字符串的事实,所以请不要使用字符串破解解决方案
我想按序列中的每个“\r”对这些元素进行分组。
也就是说,我想要一个带有“foo”、“bar”、“jar”的数组/枚举,另一个带有“a”、“b”、“c”等
ienumerable扩展中是否有任何东西可以让我这样做,或者我必须在这里按方法滚动我自己的组?为此,我编写了一个扩展方法,该方法适用于任何
ienumerable
这将打印:
foo, bar, jar
a, b, c
x, y, z
(在末尾包括一个空行,因为在您的集合末尾有一个
“\r”
。如果您想使用标准的IEnumerable
扩展方法,您必须使用Aggregate
(但这并不像Timwi的解决方案那样可重用):
var list=new[]{“foo”、“bar”、“jar”、“a”、“b”、“c”、“r”、“x”、“y”、“z”、“r”};
var res=list.Aggregate(新列表(),
(l,s)=>
{
如果(s==“\r”)
{
l、 添加(新列表());
}
其他的
{
如果(!l.Any())
{
l、 添加(新列表());
}
l、 最后()。添加(s);
}
返回l;
});
也可以看到这一点。您可以有一个SplitBy
扩展方法,该方法接受要拆分的谓词:
public static IEnumerable<IList<T>> SplitBy<T>(this IEnumerable<T> source,
Func<T, bool> separatorPredicate,
bool includeEmptyEntries = false,
bool includeSeparators = false)
{
var l = new List<T>();
foreach (var x in source)
{
if (!separatorPredicate(x))
l.Add(x);
else
{
if (includeEmptyEntries || l.Count != 0)
{
if (includeSeparators)
l.Add(x);
yield return l;
}
l = new List<T>();
}
}
if (l.Count != 0)
yield return l;
}
与Timwi相同,但实施方式不同。无错误检查,这取决于u。这会更快,因为您只遍历列表一次。可能重复的“否”,它不是重复的-另一个请求固定大小的组,这一个请求基于分隔符的拆分。@Timwi:可能是此处的关键字。。。。
foo, bar, jar
a, b, c
x, y, z
var list = new[] { "foo","bar","jar","\r","a","b","c","\r","x","y","z","\r" };
var res = list.Aggregate(new List<List<string>>(),
(l, s) =>
{
if (s == "\r")
{
l.Add(new List<string>());
}
else
{
if (!l.Any())
{
l.Add(new List<string>());
}
l.Last().Add(s);
}
return l;
});
public static IEnumerable<IList<T>> SplitBy<T>(this IEnumerable<T> source,
Func<T, bool> separatorPredicate,
bool includeEmptyEntries = false,
bool includeSeparators = false)
{
var l = new List<T>();
foreach (var x in source)
{
if (!separatorPredicate(x))
l.Add(x);
else
{
if (includeEmptyEntries || l.Count != 0)
{
if (includeSeparators)
l.Add(x);
yield return l;
}
l = new List<T>();
}
}
if (l.Count != 0)
yield return l;
}
var arr = new string[] {"foo","bar","jar","\r","a","b,"c","\r","x","y","z","\r");
foreach (var items in arr.SplitBy(x => x == "\r"))
foreach (var item in items)
{
}