在C#中查找更大字符串中子字符串的所有位置

问题描述:

我有一个大字符串需要解析,我需要找到​​的所有实例,并将每个索引存储到列表中。在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 =大串

有什么更好的想法?

下面是它的一个示例扩展方法:

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

基于我用来寻找一个更大的字符串中的字符串的多个实例的代码,你的代码看起来像:

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++; 
} 

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 

你为什么不使用内置的正则表达式类:

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

使用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

@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

抛光版+案例忽略支持:

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(); 
} 

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; 
} 

你好漂亮的答案被@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

没有正则表达式,使用字符串比较型:

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}

我注意到,至少有两个提议的解决方案不处理重叠的搜索命中。我没有检查标有绿色复选标记的那个。这里是处理重叠搜索命中的一个:

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; 
    }