C# 识别和分组字符串集合中的类似项
我有一组字符串,如下所示:C# 识别和分组字符串集合中的类似项,c#,.net,linq,C#,.net,Linq,我有一组字符串,如下所示: List<string> codes = new List<string> { "44.01", "44.02", "44.03", "44.04", "44.05", "44.06", "44.07", "44.08", "46", "47.10" }; 列表代码=新列表 { "44.01", "44.02", "44.03", "44.04", "44.05", "44.06", "44.07", "44.08", "46", "
List<string> codes = new List<string>
{
"44.01", "44.02", "44.03", "44.04", "44.05", "44.06", "44.07", "44.08", "46", "47.10"
};
列表代码=新列表
{
"44.01", "44.02", "44.03", "44.04", "44.05", "44.06", "44.07", "44.08", "46", "47.10"
};
每个字符串由两个组件组成,两个组件之间用一个句号分隔——前缀代码和子代码。有些字符串没有子代码
我希望能够组合前缀相同的字符串,并将其与其他代码一起输出,如下所示:
44(01,02,03,04,05,06,07,08),46,47.10
我被困在第一个障碍上,那就是如何识别前缀值相同的代码并将其分组,这样我就可以将它们组合成一个字符串,正如上面所示 概述想法:
- 使用
收集结果字典
- 在列表上的循环中,使用
。。第一个元素将是您的字典键。。。如果密钥还不存在,则在那里创建一个新的string.split()
列表
- 如果拆分的结果有第二个元素,请将其附加到列表中
- 使用第二个循环将该字典格式化为输出字符串
List<string> codes = new List<string>() {
"44.01", "44.05", "47", "42.02", "44.03" };
var result = string.Join(",",
codes.OrderBy(x => x)
.Select(x => x.Split('.'))
.GroupBy(x => x[0])
.Select((x) =>
{
if (x.Count() == 0) return x.Key;
else if (x.Count() == 1) return string.Join(".", x.First());
else return x.Key + "(" + string.Join(",", x.Select(e => e[1]).ToArray()) + ")";
}).ToArray());
列表代码=新列表(){
"44.01", "44.05", "47", "42.02", "44.03" };
var result=string.Join(“,”,
codes.OrderBy(x=>x)
.选择(x=>x.Split('.'))
.GroupBy(x=>x[0])
.选择((x)=>
{
如果(x.Count()==0)返回x.Key;
如果(x.Count()==1)返回string.Join(“.”,x.First());
否则返回x.Key+”(“+string.Join(“,”,x.Select(e=>e[1]).ToArray())+”);
}).ToArray());
一定要爱林克。。。哈哈。。。我认为这是一个怪物。概述了这个想法:
- 使用
收集结果字典
- 在列表上的循环中,使用
。。第一个元素将是您的字典键。。。如果密钥还不存在,则在那里创建一个新的string.split()
列表
- 如果拆分的结果有第二个元素,请将其附加到列表中
- 使用第二个循环将该字典格式化为输出字符串
List<string> codes = new List<string>() {
"44.01", "44.05", "47", "42.02", "44.03" };
var result = string.Join(",",
codes.OrderBy(x => x)
.Select(x => x.Split('.'))
.GroupBy(x => x[0])
.Select((x) =>
{
if (x.Count() == 0) return x.Key;
else if (x.Count() == 1) return string.Join(".", x.First());
else return x.Key + "(" + string.Join(",", x.Select(e => e[1]).ToArray()) + ")";
}).ToArray());
列表代码=新列表(){
"44.01", "44.05", "47", "42.02", "44.03" };
var result=string.Join(“,”,
codes.OrderBy(x=>x)
.选择(x=>x.Split('.'))
.GroupBy(x=>x[0])
.选择((x)=>
{
如果(x.Count()==0)返回x.Key;
如果(x.Count()==1)返回string.Join(“.”,x.First());
否则返回x.Key+”(“+string.Join(“,”,x.Select(e=>e[1]).ToArray())+”);
}).ToArray());
一定要爱林克。。。哈哈。。。我认为这是一个怪兽。总体思路,但我确信用
Regex
替换子字符串
调用也会更好
List<string> newCodes = new List<string>()
foreach (string sub1 in codes.Select(item => item.Substring(0,2)).Distinct)
{
StringBuilder code = new StringBuilder();
code.Append("sub1(");
foreach (string sub2 in codes.Where(item => item.Substring(0,2) == sub1).Select(item => item.Substring(2))
code.Append(sub2 + ",");
code.Append(")");
newCodes.Add(code.ToString());
}
List newcode=newlist()
foreach(代码中的字符串sub1.Select(item=>item.Substring(0,2)).Distinct)
{
StringBuilder代码=新的StringBuilder();
代码。追加(“sub1(”);
foreach(代码中的字符串sub2.Where(item=>item.Substring(0,2)==sub1)。选择(item=>item.Substring(2))
代码.追加(sub2+“,”);
代码。追加(“)”;
newCodes.Add(code.ToString());
}
总体思路,但我确信用Regex
替换子字符串
调用也会更好
List<string> newCodes = new List<string>()
foreach (string sub1 in codes.Select(item => item.Substring(0,2)).Distinct)
{
StringBuilder code = new StringBuilder();
code.Append("sub1(");
foreach (string sub2 in codes.Where(item => item.Substring(0,2) == sub1).Select(item => item.Substring(2))
code.Append(sub2 + ",");
code.Append(")");
newCodes.Add(code.ToString());
}
List newcode=newlist()
foreach(代码中的字符串sub1.Select(item=>item.Substring(0,2)).Distinct)
{
StringBuilder代码=新的StringBuilder();
代码。追加(“sub1(”);
foreach(代码中的字符串sub2.Where(item=>item.Substring(0,2)==sub1)。选择(item=>item.Substring(2))
代码.追加(sub2+“,”);
代码。追加(“)”;
newCodes.Add(code.ToString());
}
您可以执行以下操作:
var query = codes.Select(c =>
new
{
SplitArray = c.Split('.'), //to avoid multiple split
Value = c
})
.Select(c => new
{
Prefix = c.SplitArray.First(), //you can avoid multiple split if you split first and use it later
PostFix = c.SplitArray.Last(),
Value = c.Value,
})
.GroupBy(r => r.Prefix)
.Select(grp => new
{
Key = grp.Key,
Items = grp.Count() > 1 ? String.Join(",", grp.Select(t => t.PostFix)) : "",
Value = grp.First().Value,
});
这就是它的工作原理:
- 在分隔符上拆分列表中的每个项目,并使用
、前缀
和原始后缀
值
- 后一组在
前缀上
- 之后,使用
string.Join
foreach (var item in query)
{
if(String.IsNullOrWhiteSpace(item.Items))
Console.WriteLine(item.Value);
else
Console.WriteLine("{0}({1})", item.Key, item.Items);
}
产出将是:
44(01,02,03,04,05,06,07,08)
46
47.10
你可以做:
var query = codes.Select(c =>
new
{
SplitArray = c.Split('.'), //to avoid multiple split
Value = c
})
.Select(c => new
{
Prefix = c.SplitArray.First(), //you can avoid multiple split if you split first and use it later
PostFix = c.SplitArray.Last(),
Value = c.Value,
})
.GroupBy(r => r.Prefix)
.Select(grp => new
{
Key = grp.Key,
Items = grp.Count() > 1 ? String.Join(",", grp.Select(t => t.PostFix)) : "",
Value = grp.First().Value,
});
这就是它的工作原理:
- 在分隔符上拆分列表中的每个项目,并使用
、前缀
和原始后缀
值
- 后一组在
前缀上
- 之后,使用
string.Join
foreach (var item in query)
{
if(String.IsNullOrWhiteSpace(item.Items))
Console.WriteLine(item.Value);
else
Console.WriteLine("{0}({1})", item.Key, item.Items);
}
产出将是:
44(01,02,03,04,05,06,07,08)
46
47.10
你可以走两条路…我可以看到你制作一个
字典
,这样你就可以把“44”映射到一个{.01“,.02“,.03”等的列表中。这需要你在将代码添加到这个列表之前先处理代码(即,将代码的两部分分开,并处理只有一部分的情况)
或者你可以将它们放入一个分类数据集中,并提供你自己的比较器,它知道这些是代码以及如何对它们进行排序(至少这比按字母顺序分组更可靠)。不过,在这个分类数据集中进行迭代仍然需要特殊的逻辑,因此上面的Dictionary to List选项可能仍然更可取
在这两种情况下,您仍然需要处理代码中没有第二个元素的特殊情况“46”。在字典示例中,您会在列表中插入一个字符串.Empty吗?不确定如果您得到一个列表{“46”,“46.1”},您会输出什么--您会显示为“46(null,1)”还是…“46(0,1)”…或“46(,1)”或“46(1)”还是“46(1)”?你可以有两种方法…我可以看到你制作一个
字典
,这样你就可以将“44”映射到一个{.01“,.02“,.03”等的列表中。这需要你在将代码添加到这个列表之前处理代码(即,分离代码的两个部分,并处理只有一个部分的情况)