2010-04-14 187 views
48

我有一個大字符串需要解析,我需要找到​​的所有實例,並將每個索引存儲到列表中。在C#中查找更大字符串中子字符串的所有位置

所以說這段字符串在大字符串的開頭和中間,它們都會被找到,並且它們的索引將被添加到List。而List將包含0和其他索引,不管它是什麼。

我一直在玩弄和string.IndexOf確實幾乎什麼,我找了,我已經寫了一些代碼 - 但它不工作,我一直無法弄清楚到底什麼是錯的:

List<int> inst = new List<int>(); 
int index = 0; 
while (index < source.LastIndexOf("extract\"(me,i-have lots. of]punctuation", 0) + 39) 
{ 
    int src = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index); 
    inst.Add(src); 
    index = src + 40; 
} 
  • inst =名單
  • source =大串

有什麼更好的想法?

回答

90

下面是它的一個示例擴展方法:

public static List<int> AllIndexesOf(this string str, string value) { 
    if (String.IsNullOrEmpty(value)) 
     throw new ArgumentException("the string to find may not be empty", "value"); 
    List<int> indexes = new List<int>(); 
    for (int index = 0;; index += value.Length) { 
     index = str.IndexOf(value, index); 
     if (index == -1) 
      return indexes; 
     indexes.Add(index); 
    } 
} 

如果你把這個變成一個靜態類,並與using導入命名空間,它顯示爲任意字符串的方法,你可以這樣做:

List<int> indexes = "fooStringfooBar".AllIndexesOf("foo"); 
使用迭代

有關擴展方法的更多信息,http://msdn.microsoft.com/en-us/library/bb383977.aspx

另外相同:

public static IEnumerable<int> AllIndexesOf(this string str, string value) { 
    if (String.IsNullOrEmpty(value)) 
     throw new ArgumentException("the string to find may not be empty", "value"); 
    for (int index = 0;; index += value.Length) { 
     index = str.IndexOf(value, index); 
     if (index == -1) 
      break; 
     yield return index; 
    } 
} 
+5

爲什麼不使用IEnumerable 併產生返回索引而不是索引列表? – m0sa 2010-04-15 01:15:12

+1

@ m0sa:好點。爲了它的樂趣增加了另一個版本。 – 2010-04-15 08:28:42

+0

收益率的使用是否會影響業績?對象的檢索是異步還是懶惰? Os只是語法糖,兩個代碼都是一樣的? – PedroC88 2013-10-01 15:17:42

0

基於我用來尋找一個更大的字符串中的字符串的多個實例的代碼,你的代碼看起來像:

List<int> inst = new List<int>(); 
int index = 0; 
while (index >=0) 
{ 
    index = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index); 
    inst.Add(index); 
    index++; 
} 
1
public List<int> GetPositions(string source, string searchString) 
{ 
    List<int> ret = new List<int>(); 
    int len = searchString.Length; 
    int start = -len; 
    while (true) 
    { 
     start = source.IndexOf(searchString, start + len); 
     if (start == -1) 
     { 
      break; 
     } 
     else 
     { 
      ret.Add(start); 
     } 
    } 
    return ret; 
} 

這樣稱呼它:

List<int> list = GetPositions("bob is a chowder head bob bob sldfjl", "bob"); 
// list will contain 0, 22, 26 
10

你爲什麼不使用內置的正則表達式類:

public static IEnumerable<int> GetAllIndexes(this string source, string matchString) 
{ 
    matchString = Regex.Escape(matchString); 
    foreach (Match match in Regex.Matches(source, matchString)) 
    { 
     yield return match.Index; 
    } 
} 

如果您確實需要重用表達式,然後編譯它並將其緩存在某處。將matchString參數更改爲另一個重載情況下的正則表達式matchExpression。

+0

這不會編譯 – Anshul 2016-03-07 19:33:27

+0

什麼是索引?它沒有在任何地方定義。 – Saggio 2016-03-21 20:01:34

+0

我的壞它是一個殘餘。刪除該行。 – csaam 2016-03-25 01:24:55

7

使用LINQ

public static IEnumerable<int> IndexOfAll(this string sourceString, string subString) 
{ 
    return Regex.Matches(sourceString, subString).Cast<Match>().Select(m => m.Index); 
} 
+1

雖然你忘了轉義subString。 – csaam 2010-04-15 04:12:45

+0

true ... true ... – ehosca 2010-04-15 15:07:54

0

@csam在理論上是正確的,雖然他的代碼不會complie,可以refractored到

public static IEnumerable<int> IndexOfAll(this string sourceString, string matchString) 
{ 
    matchString = Regex.Escape(matchString); 
    return from Match match in Regex.Matches(sourceString, matchString) select match.Index; 
} 
+0

如果他的代碼不正確,您可以編輯他的帖子以糾正它 – caesay 2012-12-13 20:09:42

+0

我沒有注意到這一點。我不得不承認不願意這樣做,以防萬一我錯了,儘管我不認爲我是。 – arame3333 2012-12-13 22:49:08

+0

對於大字符串使用正則表達式不是個好主意。該方法需要大量的內存。 – W92 2016-07-02 16:22:02

4

拋光版+案例忽略支持:

public static int[] AllIndexesOf(string str, string substr, bool ignoreCase = false) 
{ 
    if (string.IsNullOrWhiteSpace(str) || 
     string.IsNullOrWhiteSpace(substr)) 
    { 
     throw new ArgumentException("String or substring is not specified."); 
    } 

    var indexes = new List<int>(); 
    int index = 0; 

    while ((index = str.IndexOf(substr, index, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) != -1) 
    { 
     indexes.Add(index++); 
    } 

    return indexes.ToArray(); 
} 
0
public static Dictionary<string, IEnumerable<int>> GetWordsPositions(this string input, string[] Susbtrings) 
{ 
    Dictionary<string, IEnumerable<int>> WordsPositions = new Dictionary<string, IEnumerable<int>>(); 
    IEnumerable<int> IndexOfAll = null; 
    foreach (string st in Susbtrings) 
    { 
     IndexOfAll = Regex.Matches(input, st).Cast<Match>().Select(m => m.Index); 
     WordsPositions.Add(st, IndexOfAll); 

    } 
    return WordsPositions; 
} 
1

你好漂亮的答案被@Matti Virkkunen

public static List<int> AllIndexesOf(this string str, string value) { 
    if (String.IsNullOrEmpty(value)) 
     throw new ArgumentException("the string to find may not be empty", "value"); 
    List<int> indexes = new List<int>(); 
    for (int index = 0;; index += value.Length) { 
     index = str.IndexOf(value, index); 
     if (index == -1) 
      return indexes; 
     indexes.Add(index); 
     index--; 
    } 
} 

但這套測試情況下,像AOOAOOA 其中子

是AOOA和AOOA

輸出0和3

0

沒有正則表達式,使用字符串比較型:

string search = "123aa456AA789bb9991AACAA"; 
string pattern = "AA"; 
Enumerable.Range(0, search.Length) 
    .Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; }) 
    .Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length),StringComparison.OrdinalIgnoreCase)) 
    .Select(searchbit => searchbit.Index) 

這個返回ns {3,8,19,22}。空模式可以匹配所有位置。

的多模式:

string search = "123aa456AA789bb9991AACAA"; 
string[] patterns = new string[] { "aa", "99" }; 
patterns.SelectMany(pattern => Enumerable.Range(0, search.Length) 
    .Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; }) 
    .Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length), StringComparison.OrdinalIgnoreCase)) 
    .Select(searchbit => searchbit.Index)) 

這返回{3,8,19,22,15,16}

0

我注意到,至少有兩個提議的解決方案不處理重疊的搜索命中。我沒有檢查標有綠色複選標記的那個。這裏是處理重疊搜索命中的一個:

public static List<int> GetPositions(this string source, string searchString) 
    { 
     List<int> ret = new List<int>(); 
     int len = searchString.Length; 
     int start = -1; 
     while (true) 
     { 
      start = source.IndexOf(searchString, start +1); 
      if (start == -1) 
      { 
       break; 
      } 
      else 
      { 
       ret.Add(start); 
      } 
     } 
     return ret; 
    } 
相關問題