2015-06-02 91 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(); 
}