2017-01-28 46 views
0

我有一個List<string>的子字符串可能或可能不包含在一個較大的主要字符串。例如:如何查找子串列表中第一次出現的子串?

List<string> subStringList = new List<string>(){" at ", " @ "," near "," by "," above "}; 
List<string> searchStringList = new List<string>{ 
"GULF ISLAND POND NEAR LEWISTON, ME", 
"South Branch Raritan River near High Bridge NJ", 
"Susquehanna R near Browns Island at Dalmatia, PA", 
"PARKS CREEK AT LYLE FIELD RD NEAR JEFFERSON, GA", 
"HOMOSASSA R AT HOMOSASSA FL", 
"ST. CLAIR RIVER NEAR ROBERTS LANDING, MI" 
}; 

我想要做的是找到其在給定的搜索字符串的第一subStringList的元素,然後返回搜索字符串到這一點。

例如:

List<string> riverList = new List<string>(); 
foreach (var seachString in searchStringList) 
{ 
    string river = seachString.ToLower(); 
    int minIndex = int.MaxValue; 
    foreach (var subString in subStringList.Select(r => r.ToLower()).AsEnumerable()) 
    { 
     var index = river.IndexOf(subString); 
     if (index != null && index > -1 && index < minIndex) 
      minIndex = index; 
    } 
     riverList.Add(seachString.Substring(0,minIndex)); 
} 

輸出應該是這個樣子:

[0]: "GULF ISLAND POND" 
[1]: "South Branch Raritan River" 
[2]: "Susquehanna R" 
[3]: "PARKS CREEK" 
[4]: "HOMOSASSA R" 
[5]: "ST. CLAIR RIVER" 

我的代碼似乎工作,但有一個更有效的方式做這樣的事情,以及如何Linq可以做到這樣嗎?

+0

您的意思是「我想要做的是找到subStringList的元素,它在給定的搜索字符串中出現FIRST,然後返回searchString到那個點」 –

+0

是的,這是對問題的更好的描述。 –

+0

在您當前的代碼中,由於IndexOf(ss)永遠不會返回null,因此不需要「Index!= null」。此外,如果您正在搜索的字符串沒有搜索字符串中的一個......您當前的代碼將崩潰。 – JohnG

回答

2

這將是很好有一個過載String.IndexOfAny()這需要String[]而不是char[]。這裏是我的:

searchStringList.Select(s => s.SubstringAsFarAsIndexOfAny(subStringList)); 


public static class stringExt 
{ 
    public static int IndexOfAny(this string s, IEnumerable<string> anyOf, StringComparison stringComparisonType=StringComparison.CurrentCultureIgnoreCase) 
    { 
     var founds= anyOf.Select(sub=> s.IndexOf(sub,stringComparisonType)).Where(i => i>=0); 
     return founds.Any() ? founds.Min() : -1; 
    } 

    public static string SubstringAsFarAsIndexOfAny(this string s, IEnumerable<string> anyOf, StringComparison stringComparisonType=StringComparison.CurrentCultureIgnoreCase) 
    { 
     var foundIndex= s.IndexOfAny(anyOf,stringComparisonType); 
     return foundIndex >=0 ? s.Substring(0, foundIndex) : s; 
    } 
} 
+0

相當完美的解決方案,雖然在我的理解'StringComparison.OrdinalIgnoreCase'是一個更好的選擇,除非我們正在處理文化特定的應用程序,+1 –

+0

'founds。任何() ? found.Min()'枚舉兩次。你應該真的添加一個'ToArray()'來防止這種情況。 – CSharpie

+0

不應該。 Any()不會枚舉&Where()和Select()都針對數組,列表和迭代器進行優化:https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,4158286b17727025 –

0

這裏是一種使用LINQ做到這一點:

var result = from str in searchStringList 
      from substr in subStringList 
      let index = str.IndexOf(substr, StringComparison.OrdinalIgnoreCase) 
      where index > -1 
      select str.Remove(index); 
+0

這比輸入行返回更多的輸出行。 www.Linqpad.net很適合測試片段:-) –

0

我已經簡化了您與相關意見實施了代碼,查是否有所幫助:

List<string> riverList = new List<string>(); 

    // Traverse through search string list 
    foreach (var searchString in searchStringList) 
    { 
     // Set the default min index value to -1 
     int minIndex = -1; 
     // Traverse through sub string list 
     foreach (var subString in subStringList) 
     { 
      // Fetch first index 
      var index = searchString.IndexOf(subString,StringComparison.OrdinalIgnoreCase); 

      // Reset Min Index logic 
      if(minIndex == -1) 
       minIndex = index; 
      else if(minIndex > index && index != -1) 
       minIndex = index; 

      // Break the processing of substrings if minindex is 0 (starting point) 
      if(minIndex == 0) 
      break; 
     }  

     riverList.Add(searchString.Substring(0, minIndex)); 
    } 
0

被更新(因爲當有在substringList匹配字符串的情況下):這裏與默認LINQ方法的一串溶液而沒有任何擴展名:

var result = searchStringList 
       .Select(searchString => 
        searchString.Substring(0, 
         subStringList.Select(
           substring => searchString.IndexOf(substring, StringComparison.InvariantCultureIgnoreCase)) 
          .Where(s => s > -1)        
          .DefaultIfEmpty(0) 
          .Min())) 
          .Where(x => !string.IsNullOrEmpty(x));        
+0

如果搜索的字符串不在搜索的字符串中,是否可以編寫代碼以防止崩潰? – JohnG

+0

更新爲你提到的情況 –

+0

謝謝,這似乎像預期的那樣使用LINQ。有沒有一種方法可以解決搜索字符串在字符串乞求處的問題:「@ ST。CLAIR RIVER ROBERTS LANDING,MI」?你的代碼似乎不能識別這些行。 – JohnG

0

一般的LINQ替代for循環是Aggregate()

searchStringList.Select(s => s.SubstringAsFarAsIndexOfAny(subStringList)); 


public static class stringExt 
{ 
    public static int IndexOfAny(this string s, IEnumerable<string> anyOf, StringComparison stringComparisonType=StringComparison.CurrentCultureIgnoreCase) 
    { 
    var best = anyOf 
       .Select(sub => s.IndexOf(sub, stringComparisonType)) 
       .Aggregate(
         int.MaxValue, 
         (bestSoFar, current) => 0 <= current && current < bestSoFar ? current : bestSoFar 
        ); 
    return best == int.MaxValue ? -1 : best; 
    } 

    public static string SubstringAsFarAsIndexOfAny(this string s, IEnumerable<string> anyOf, StringComparison stringComparisonType=StringComparison.CurrentCultureIgnoreCase) 
    { 
     var foundIndex= s.IndexOfAny(anyOf,stringComparisonType); 
     return foundIndex >=0 ? s.Substring(0, foundIndex) : s; 
    } 
} 

我懷疑很多人會發現這個更具可讀性。

相關問題