在C#中查找大string中的子string的所有位置

我有一个大的string,我需要parsing,我需要find所有的extract"(me,i-have lots. of]punctuation实例extract"(me,i-have lots. of]punctuation ,并将它们存储到列表中。

所以说这段string在大string的开始和中间,都会被find,并且它们的索引将被添加到List 。 而List将包含0和另一个索引,不pipe它是什么。

我一直在玩耍, 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 =大string

任何更好的想法?

这是一个扩展方法的例子:

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

如果你把它放到一个静态类中,并usingusing导入命名空间,那么它就会以任何string的方式出现,你可以这样做:

 List<int> indexes = "fooStringfooBar".AllIndexesOf("foo"); 

有关扩展方法的更多信息,请参阅http://msdn.microsoft.com/zh-cn/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; } } 

为什么不使用内build的RegEx类:

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

如果您确实需要重用expression式,那么编译它并将其caching在某处。 将matchString参数更改为另一个重载情况下的正则expression式matchExpression。

使用LINQ

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

抛光版+忽略支持的情况:

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

嗨好回答@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这样的子串的testing用例

是AOOA和AOOA

输出0和3

根据我用于在更大的string中查找多个string实例的代码,您的代码如下所示:

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

没有正则expression式,使用string比较types:

 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) 

这返回{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}

@csam在理论上是正确的,尽pipe他的代码不会被编译和折射

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