字符串列表示例:
var test = new List<string>{
"hdr1","abc","def","ghi","hdr2","lmn","opq","hdr3","rst","xyz"
};
我想用"hdr*"
来划分这个列表,这样每个组都包含元素.
"hdr1","abc","def","ghi"
"hdr2","lmn","opq",
"hdr3","rst","xyz"
我试过:
var result = test.GroupBy(g => g.StartsWith("hdr"));
但这给了我两组
"hdr1","hdr2","hdr3"
"abc","def"..."xyz"
正确的LINQ语句是什么?让我强调一下,"hdr*"
后面的字符串可以是任何东西。他们唯一的共同点就是遵循"hdr*"
。
发布于 2022-09-03 16:46:46
您可以得到两个组,因为一个组是以"hdr"
开头的元素组,另一个组是不以"hdr"
开头的元素组。StartsWith
返回一个bool
,因此这将导致两个组拥有密钥false
和true
。
可以在LINQ中使用语句块。这使我们能够:
string header = null;
var groups = test
.Select(s => {
if (s.StartsWith("hdr")) header = s;
return s;
})
.Where(s => header != s)
.GroupBy(s => header);
我们将最后一个头存储在header
中。where子句消除标头本身,因为标头是组键。
接下来的测试..。
foreach (var g in groups) {
Console.WriteLine(g.Key);
foreach (var item in g) {
Console.WriteLine(" " + item);
}
}
..。用给定的列表打印该列表:
hdr1
abc
def
ghi
hdr2
lmn
opq
hdr3
rst
xyz
相反,我们还可以创建以头作为第一个元素的列表:
string header = null;
IEnumerable<List<string>> lists = test
.Select(s => {
if (s.StartsWith("hdr")) {
header = s;
}
return s;
})
.GroupBy(s => header)
.Select(g => g.ToList());
这个测试..。
foreach (var l in lists) {
foreach (var item in l) {
Console.Write(item + " ");
}
Console.WriteLine();
}
..。指纹:
hdr1 abc def ghi
hdr2 lmn opq
hdr3 rst xyz
发布于 2022-09-03 16:51:33
您可以制作一个花哨的可拓法 GroupWhen
,当它找到匹配项时启动一个新组。就像IEnumerable.GroupBy
一样,它将返回一个组的“列表”:
public static IEnumerable<IGrouping<int, T>> GroupWhen<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
var i = 0;
// This method "marks" which group each item belongs in
// by creating a Tuple with the item and group number
IEnumerable<(T Item, int GroupNum)> Iterate()
{
foreach (var item in source)
{
if (predicate(item)) i++; // Start new group
yield return (item, i);
}
}
// Group items by the "mark" from above and only
// output the Item from the Tuple, since the
// GroupNum will be the 'int' key of the group
return Iterate().GroupBy(tup => tup.GroupNum, tup => tup.Item);
}
// Use like so:
var list = new List<string> {"hdr1","abc","def","ghi","hdr2","lmn","opq","hdr3","rst","xyz"};
var groups = list.GroupWhen(s => s.StartsWith("hdr"))
Console.WriteLine(string.Join(",", groups.First()))
// hdr1,abc,def,ghi
请查看这把小提琴进行测试运行。
发布于 2022-09-03 16:52:15
是的,你可以用LINQ表达式来做。但我不认为它比前景循环可读性强。
var test = new List<string>{
"hdr1","abc","def","ghi","hdr2","lmn","opq","hdr3","rst","xyz"
};
int groupid = 0;
var result = test.GroupBy(t =>
{
if (t.StartsWith("hdr")) ++groupid;
return groupid;
}).ToList();
result.Select(t => string.Join(' ', t)).ToList().ForEach(Console.WriteLine);
/*
Outputs:
hdr1 abc def ghi
hdr2 lmn opq
hdr3 rst xyz
*/
https://stackoverflow.com/questions/73593578
复制相似问题