如何使用C#从字符串列表中提取公共部分

时间:2012-12-22 10:33:38

标签: c# linq

这是我的情景!

List<String> list = new List<String>();
list.Add("E9215001");
list.Add("E9215045");
list.Add("E1115001");
list.Add("E1115022");
list.Add("E1115003");
list.Add("E2115041");
list.Add("E2115042");
list.Add("E4115021");
list.Add("E5115062");

我需要使用C#和&amp ;;从上面的列表中提取以下常用部分。 LINQ

E92150 - &gt;摘自{* E92150 * 01,* E92150 * 45}

E11150 - &gt;摘自{* E11150 * 01,* E11150 * 22,* E11150 * 03}

E21150 - &gt;摘自{* E21150 * 41,* E21150 * 42}

E41150 - &gt;摘自{* E41150 * 21}

E51150 - &gt;摘自{* E51150 * 62}

更新:谢谢!大家!在@mlorbetske&amp;的帮助下@shelleybutterfly我已经弄明白了!

解决方案:

list.Select((item, index) => new {
Index=index, 
Length=Enumerable.Range(1, (item.Length-2)) //I'm ignoring the last 2 characters
                 .Reverse()
                 .First(proposedLength => list.Count(innerItem =>  
                   innerItem.StartsWith(item.Substring(0, proposedLength))) > 
                   1)}).Select(n => list[n.Index].Substring(0, n.Length)).Distinct()

4 个答案:

答案 0 :(得分:5)

我怀疑这是你正在寻找的,但是

var result = list.Select(s => s.Substring(0, 6))
                 .Distinct();

答案 1 :(得分:1)

我不确定确定比赛的标准是什么,所以我写了这篇文章 - 它是完全新颖的,99.9999%确定它实际上并不是你想要的。

基本上,外部选择获取所确定长度的所有子串。

第一个内部选择确定在列表中至少一个其他字符串中找到的此字符串的最大长度。

group by(在第一个内部选择之后)自己对找到的长度进行分组。

然后将此分组转换为长度与其找到次数的字典。

然后我们按频率(Value)命令这组分组找到长度(升序)。

接下来,我们取实际长度(最不常出现的长度 - 来自Key)并将其吐回到Substring的第二个参数中,因此我们将从0到该长度的子串。当然,我们现在回到外部选择,所以我们实际上正在获得价值(万岁!)。

现在,我们从该结果中获取不同的值集,瞧!

list.Select(
    item => item.Substring(0, 
        list.Select(
            innerItem => Enumerable.Range(1, innerItem.Length)
                           .Reverse()
                           .First(proposedlength => list.Count(innerInnerItem => innerInnerItem.StartsWith(innerItem.Substring(0, proposedlength))) > 1)
                   )
            .GroupBy(length => length)
            .ToDictionary(grouping => grouping.Key, grouping => grouping.Count())
            .OrderBy(pair => pair.Value)
            .Select(pair => pair.Key)
            .First())
        ).Distinct()

在阅读上述评论后,我发现每个学期都有兴趣找到其他任何一个中存在的最长的子串。这里有更新颖的代码:

list.Select((item, index) => new {
    Index=index, 
    Length=Enumerable.Range(1, item.Length)
                     .Reverse()
                     .First(proposedLength => list.Count(innerItem => innerItem.StartsWith(item.Substring(0, proposedLength))) > 1)
}).Select(n => list[n.Index].Substring(0, n.Length))
  .Distinct()

简而言之,遍历列表中的每个项目并收集条目的索引和该元素开头的最长子字符串,该子字符串可以在列表中的至少一个其他条目中找到。通过从每个索引/长度对收集所有子串并仅采用不同的字符串集来跟随它。

答案 2 :(得分:0)

是否需要内联查询语法?如果是这样,那怎么样:

var result =
    from item in list
    select item.Substring(0,6);

或具有不同要求:

var result =
    (
        from item in list
        select item.Substring(0,6);
    )
    .Distinct();

答案 3 :(得分:0)

<强>解决!感谢@ mlorbetske 和@ shelleybutterfly

list.Select((item, index) => new { Index=index, 
            Length=Enumerable.Range(1, (item.Length-2)) //I don't need the last 2 Char so I'm ignoring it
            .Reverse()
            .First(proposedLength => list.Count(innerItem =>  
             innerItem.StartsWith(item.Substring(0, proposedLength))) > 
             1)}).Select(n => list[n.Index].Substring(0, n.Length)).Distinct()