检查字符串是否包含列表中的元素(字符串)

时间:2009-02-01 14:37:50

标签: c# vb.net list coding-style performance

对于以下代码块:

For I = 0 To listOfStrings.Count - 1
    If myString.Contains(lstOfStrings.Item(I)) Then
        Return True
    End If
Next
Return False

输出结果为:

案例1:

myString: C:\Files\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: True

案例2:

myString: C:\Files3\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: False

列表(listOfStrings)可能包含多个项目(最少20个),必须根据数千个字符串(如myString)进行检查。

是否有更好(更有效)的方法来编写此代码?

13 个答案:

答案 0 :(得分:293)

使用LINQ,并使用C#(这些天我不太了解VB):

bool b = listOfStrings.Any(s=>myString.Contains(s));

或(更短,更有效,但可以说不太清楚):

bool b = listOfStrings.Any(myString.Contains);

如果您正在测试相等性,那么值得查看HashSet等,但这对部分匹配没有帮助,除非您将其拆分为片段并添加复杂的顺序。


更新:如果你的意思是“StartsWith”,那么你可以对列表进行排序并将其放入数组中;然后使用Array.BinarySearch查找每个项目 - 通过查找检查它是完全匹配还是部分匹配。

答案 1 :(得分:6)

当你构造你的字符串时,它应该是这样的

bool inact = new string[] { "SUSPENDARE", "DIZOLVARE" }.Any(s=>stare.Contains(s));

答案 2 :(得分:5)

早先的类似问题“Best way to test for existing string against a large list of comparables”提出了许多建议。

正则表达式可能足以满足您的要求。表达式将是所有候​​选子串的串联,它们之间具有OR“|”运算符。当然,在构建表达式时,您必须注意未转义的字符,或者由于复杂性或大小限制而无法编译它。

另一种方法是构造一个trie data structure来表示所有候选子串(这可能与正则表达式匹配器正在做的有些重复)。当您遍历测试字符串中的每个字符时,您将创建一个指向trie根的新指针,并将现有指针推进到相应的子节点(如果有)。当任何指针到达叶子时,你会得到一个匹配。

答案 3 :(得分:3)

我喜欢Marc的答案,但需要包含匹配才能成为CaSe InSenSiTiVe。

这是解决方案:

bool b = listOfStrings.Any(s => myString.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0))

答案 4 :(得分:2)

根据您的模式,一个改进是改为使用StartsWith而不是Contains。 StartsWith只需迭代遍历每个字符串,直到找到第一个不匹配,而不是必须在找到每个字符位置时重新开始搜索。

此外,根据您的模式,看起来您可能能够提取myString路径的第一部分,然后反转比较 - 在​​字符串列表中查找myString的起始路径而不是其他四处走动。

string[] pathComponents = myString.Split( Path.DirectorySeparatorChar );
string startPath = pathComponents[0] + Path.DirectorySeparatorChar;

return listOfStrings.Contains( startPath );

编辑:使用HashSet构思@Marc Gravell提及的速度更快,因为您可以将Contains更改为ContainsKey,而查找将为O(1) O(N)。您必须确保路径完全匹配。请注意,这不是像@Marc Gravell那样的通用解决方案,而是根据您的示例量身定制的。

抱歉C#示例。我没有足够的咖啡来翻译成VB。

答案 5 :(得分:1)

我不确定它是否更有效率,但您可以考虑在Lambda Expressions使用。

答案 6 :(得分:1)

你测试了速度吗?

即。您是否创建了一组样本数据并对其进行了分析?它可能没有你想象的那么糟糕。

这也可能是你可以产生一个单独的线程并给出速度幻觉的东西!

答案 7 :(得分:0)

如果速度至关重要,您可能需要查找Aho-Corasick algorithm的模式集。

它是一个带有失败链接的trie,即复杂度为O(n + m + k),其中n是输入文本的长度,m是模式的累积长度,k是数量火柴。您只需在找到第一个匹配项后修改算法即可终止。

答案 8 :(得分:0)

myList.Any(myString.Contains);

答案 9 :(得分:0)

Contains方法的缺点是它不允许指定比较类型,这在比较字符串时通常很重要。它始终对文化和大小写敏感。因此,我认为WhoIsRich的答案很有价值,我只想显示一个更简单的选择:

listOfStrings.Any(s => s.Equals(myString, StringComparison.OrdinalIgnoreCase))

答案 10 :(得分:0)

老问题。但是由于VB.NET是最初的要求。使用可接受的答案的相同值:

listOfStrings.Any(Function(s) myString.Contains(s))

答案 11 :(得分:0)

由于我需要检查(长)字符串中的列表中是否有项目,所以我得到了这个:

listOfStrings.Any(x => myString.ToUpper().Contains(x.ToUpper()));

或在vb.net中:

listOfStrings.Any(Function(x) myString.ToUpper().Contains(x.ToUpper()))

答案 12 :(得分:0)

略有变化,我需要找出字符串中是否有完整的单词并且不区分大小写。

myString.Split(' ', StringSplitOptions.RemoveEmptyEntries).Intersect(listOfStrings).Any())

不区分大小写的 myStringlistOfStrings 已转换为大写。