首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用linq将字符串列表分组在特定字符串上

如何使用linq将字符串列表分组在特定字符串上
EN

Stack Overflow用户
提问于 2022-09-03 15:52:35
回答 3查看 74关注 0票数 0

字符串列表示例:

代码语言:javascript
运行
复制
var test = new List<string>{
    "hdr1","abc","def","ghi","hdr2","lmn","opq","hdr3","rst","xyz"
};

我想用"hdr*"来划分这个列表,这样每个组都包含元素.

代码语言:javascript
运行
复制
"hdr1","abc","def","ghi"  
"hdr2","lmn","opq",  
"hdr3","rst","xyz"  

我试过:

代码语言:javascript
运行
复制
var result = test.GroupBy(g => g.StartsWith("hdr"));

但这给了我两组

代码语言:javascript
运行
复制
"hdr1","hdr2","hdr3"  
"abc","def"..."xyz"  

正确的LINQ语句是什么?让我强调一下,"hdr*"后面的字符串可以是任何东西。他们唯一的共同点就是遵循"hdr*"

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-09-03 16:46:46

您可以得到两个组,因为一个组是以"hdr"开头的元素组,另一个组是不以"hdr"开头的元素组。StartsWith返回一个bool,因此这将导致两个组拥有密钥falsetrue

可以在LINQ中使用语句块。这使我们能够:

代码语言:javascript
运行
复制
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子句消除标头本身,因为标头是组键。

接下来的测试..。

代码语言:javascript
运行
复制
foreach (var g in groups) {
    Console.WriteLine(g.Key);
    foreach (var item in g) {
        Console.WriteLine("    " + item);
    }
}

..。用给定的列表打印该列表:

代码语言:javascript
运行
复制
hdr1
    abc
    def
    ghi
hdr2
    lmn
    opq
hdr3
    rst
    xyz

相反,我们还可以创建以头作为第一个元素的列表:

代码语言:javascript
运行
复制
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());

这个测试..。

代码语言:javascript
运行
复制
foreach (var l in lists) {
    foreach (var item in l) {
        Console.Write(item + " ");
    }
    Console.WriteLine();
}

..。指纹:

代码语言:javascript
运行
复制
hdr1 abc def ghi
hdr2 lmn opq
hdr3 rst xyz
票数 1
EN

Stack Overflow用户

发布于 2022-09-03 16:51:33

您可以制作一个花哨的可拓法 GroupWhen,当它找到匹配项时启动一个新组。就像IEnumerable.GroupBy一样,它将返回一个组的“列表”:

代码语言:javascript
运行
复制
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

请查看这把小提琴进行测试运行。

票数 1
EN

Stack Overflow用户

发布于 2022-09-03 16:52:15

是的,你可以用LINQ表达式来做。但我不认为它比前景循环可读性强。

代码语言:javascript
运行
复制
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
 */
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73593578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档