在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;
}
}
基于我用来寻找一个更大的字符串中的字符串的多个实例的代码,你的代码看起来像:
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。
@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;
}
抛光版+案例忽略支持:
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;
}
为什么不使用IEnumerable并产生返回索引而不是索引列表? –
m0sa
2010-04-15 01:15:12
@ m0sa:好点。为了它的乐趣增加了另一个版本。 – 2010-04-15 08:28:42
收益率的使用是否会影响业绩?对象的检索是异步还是懒惰? Os只是语法糖,两个代码都是一样的? – PedroC88 2013-10-01 15:17:42