2015-06-02 92 views
3

我想比较一个字符串集合并返回相等的部分,直到出现不相等的部分。 (并删除traling空格)。比较字符串是否相等

例如:

List<string> strList = new List<string> 
{ 
    "string xyz stop", 
    "string abc stop", 
    "string qrt stop" 
}; 

string result = GetEqualName(strList); // This should return "string" 

我提出了以下方法,工程

string GetEqualName(IEnumerable<string> strList) 
{ 
    string outString = ""; 
    bool firstTime = true; 
    foreach (var subString in strList) 
    { 
     if (firstTime) 
     { 
      outString = subString; 
      firstTime = false; 
     } 
     else 
     { 
      string stringBuilder = ""; 
      for (int i = 0; i < outString.Count(); i++) 
      { 
       if (outString[i] == subString[i]) 
        stringBuilder = stringBuilder + outString[i]; 
       else 
        break; 
      } 
      outString = stringBuilder; 
     } 
    } 
    outString = outString.TrimEnd(' '); // Remove traling whitespace 
    return outString; 
} 

我只是觉得这是一件可以在几行来,我矫枉过正。你们有什么建议吗?

+3

你的例子似乎是比较三个字符串,而不是你说的两个字符串。 –

+2

我不知道任何内置函数会将其减少到几行(Linq聚合的“巧妙”使用除外)。如果你的方法有效(并且你理解_why_它有效),那么我没有看到改变它的强制理由。 –

+0

“subString”可能是错误的单词使用。它是集合中的一个字符串。 – Daltons

回答

6

你可以将Zip两个字符串放在一起,取对数相等的字符串,然后创建一个字符串。

public static string LargestCommonPrefix(string first, string second) 
{ 
    return new string(first.Zip(second, Tuple.Create) 
     .TakeWhile(pair => pair.Item1 == pair.Item2) 
     .Select(pair => pair.Item1) 
     .ToArray()); 
} 

一旦你已经解决了这个问题对于合并两个字符串的情况下,您可以轻松地将其应用到串序列:

public static string LargestCommonPrefix(IEnumerable<string> strings) 
{ 
    return strings.Aggregate(LargestCommonPrefix); 
} 
+1

不错的使用Aggregate来解释“处理两个案例,然后扩展”的概念 –

+0

真的令人印象深刻 –

2

这个小功能做基本相同的版本,但更短。

string GetEqualName(IEnumerable<string> strList) 
{ 
    int limit = strList.Min(s => s.Length); 

    int i = 0; 
    for (; i < limit; i++) 
    { 
     if (strList.Select(s => s.Substring(0,i+1)).Distinct().Count() > 1) 
     { 
      break; 
     } 
    } 
    return strList.First().Substring(0, i).Trim(); 
} 
+0

请注意,这是*超*低效。除了这里没有短路的事实之外,你一直在不断地做同样的工作,所以你要计算所有长度小于或等于所有字符串的所有子字符串最终的价值。 – Servy

+0

我从来没有说过它会更快;)尽管如此,在字符串变大之前,差异非常小。我实际上正在研究一个更快的版本,但是a)这是一个在等待工作时编写的快速发布的答案,以及b)当提问者的名字是“我对这个还很新”时,问题是关于像比较字符串一样简单(至少在表面上),我认为一个易于理解的版本可能会被赞赏。高效版本将使用'.TakeWhile()'或条件zip。此外,它击败了一个'StringBuilder'! – anaximander

1

这是一个不同的方法,它可以做你想做的。我寻找最长公共子从左至右用HashSet<string>

string GetCommonStartsWith(IEnumerable<string> strList, StringComparer comparer = null) 
{ 
    if(!strList.Any() || strList.Any(str => string.IsNullOrEmpty(str))) 
     return null; 
    if(!strList.Skip(1).Any()) 
     return strList.First(); // only one 

    if(comparer == null) comparer = StringComparer.CurrentCulture; 
    int commonLength = strList.Min(str => str.Length); 

    for (int length = commonLength; length > 0; length--) 
    { 
     HashSet<string> duptester = new HashSet<string>(comparer); 
     string first = strList.First().Substring(0, length).TrimEnd(); 
     duptester.Add(first); 
     bool allEqual = strList.Skip(1) 
      .All(str => !duptester.Add(str.Substring(0, length).TrimEnd())); 
     if (allEqual) 
      return first; 
    } 
    return null; 
} 
1

下面是一个使用LINQ较少比一些其他的答案,并有可能会成为更高性能的版本。

string GetEqualName(IEnumerable<string> strList) 
{ 
    StringBuilder builder = new StringBuilder(); 
    int minLength = strList.Min(s => s.Length); 

    for (int i = 0; i < minLength; i++) 
    { 
     char? c = null; 
     foreach (var s in strList) 
     { 
      if (c == null) 
       c = s[i]; 
      else if (s[i] != c) 
       return builder.ToString().TrimEnd(); 
     } 
     builder.Append(c); 
    } 
    return builder.ToString().TrimEnd(); 
}