我是Linq的新手,我正在尝试将我的一个SQL查询转换为C#来实现这一目标。我们假设我有以下字符串:
ABC-pqr-cv3-xa
LKJ-eqq-cb2-ya
POI-qqq-aaa-1
ABC-pqr-cv3-xb
UIO-qqq-xa
LKJ-eqq-cb2-za
POI-qqq-aaa-2
UIO-qqq-xb
LKJ-eqq-cb2-yb
POI-qqq-aaa-3
我想根据整个字符串是否与最后一个字符匹配来对这些字符串进行分组。因此,以下是我期望的输出:
ABC-pqr-cv3-xa -- 1
ABC-pqr-cv3-xb -- 1
LKJ-eqq-cb2-ya -- 2
LKJ-eqq-cb2-yb -- 2
UIO-qqq-xa -- 3
UIO-qqq-xb -- 3
POI-qqq-aaa-1 -- 4
POI-qqq-aaa-2 -- 4
POI-qqq-aaa-3 -- 4
LKJ-eqq-cb2-za -- 5
天真地做这件事需要进行O(n ^ 2)比较。有没有更好的方法来实现这一目标?群组编号本身并不重要。我正在尝试这个,如果我找到一个有效的方法,我会发一个答案。
答案 0 :(得分:5)
myLotsOfStrings.GroupBy(item => item.Substring(-1))
将产生IEnumerable<IGrouping<string,string>>
,其中IGrouping<string,string>
是该组中IEnumerable<string>
项。
它是使用ILookup
构建的,在创建时,它只迭代源一次并构建一个类似字典的结构,允许每个键有多个值。它可能会尽可能高效......更像O(N)。
鉴于您在下面的评论中列出的约束,您可能需要正则表达式来修剪您的组密钥。
正则表达式:
(^.*-(?=\d+$))|(^.*-[^-]*(?=[^-]$))
匹配POI-qqq-aaa-
的{{1}}和POI-qqq-aaa-123
的{{1}}。
所以把它们放在一起......
POI-qqq-aaa-xv
似乎可以解决问题。
答案 1 :(得分:1)
我真的很喜欢花钱的答案的简洁,但我想我会使用更多的SQL linq语法添加一些东西(因为这是你所熟悉的)。其中大部分是设置和输出: - )
var d =
@"ABC-pqr-cv3-xa
LKJ-eqq-cb2-ya
POI-qqq-aaa-1
ABC-pqr-cv3-xb
UIO-qqq-xa
LKJ-eqq-cb2-za
POI-qqq-aaa-2
UIO-qqq-xb
LKJ-eqq-cb2-yb
POI-qqq-aaa-3";
var lines = d.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
var grp = from line in lines
group line by line.Substring(0, line.Length - 1) into g
select g;
int i = 1;
foreach (var g in grp) {
Console.WriteLine(i++);
foreach (var s in g) {
Console.WriteLine("\t{0}", s);
}
}