检查一个string是否包含列表中的元素(string)

对于以下代码块:

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)可能包含几个项目(最less20),它必须检查数千个string(如myString)。

有没有更好(更有效)的方式来编写这段代码?

使用LINQ,并使用C#(我最近不知道VB):

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

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

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

如果你正在testing平等,那么值得看一下HashSet等,但这不会有助于部分匹配,除非你把它分成片段和添加一个复杂的顺序。


更新:如果您的意思是“StartsWith”,那么您可以对列表进行sorting并将其放入数组; 然后使用Array.BinarySearch来查找每个项目 – 通过查找来检查是否是全部或部分匹配。

早先的一个类似的问题“从大量可比对象列表中检测现有string的最佳方法 ”中提出了一些build议。

正则expression式可能已经足够满足您的需求。 该expression式将是所有候​​选子string的串联,在它们之间带有OR“ | ”运算符。 当然,在构buildexpression式时,不得不注意非转义字符,或者由于复杂性或大小限制而无法编译它。

另一种方法是构造一个trie数据结构来表示所有的候选子string(这可能有点重复正则expression式匹配器正在做什么)。 当你遍历testingstring中的每个字符时,你会创build一个新的指向树的根的指针,并将现有的指针提前到适当的子节点(如果有的话)。 当任何指针到达叶子时,你会得到一个匹配。

当你构build你的string应该是这样的

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

根据你的模式,一个改进就是改用StartsWith而不是Contains。 开始只需遍历每个string,直到find第一个不匹配,而不必在每个字符位置重新开始search。

此外,根据您的模式,看起来您可能能够提取myStringpath的第一部分,然后反转比较 – 在​​string列表中查找myString的起始path,而不是以其他方式查找。

 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)。 你将不得不确保path完全匹配。 请注意,这不是@Marc Gravell's的一般解决scheme,而是根据您的示例进行量身定制的。

对不起,对于C#的例子。 我没有足够的咖啡来转换为VB。

我不确定它是否更有效,但是您可以考虑在Lambdaexpression式中使用 。

你testing过速度了吗?

即,您是否创build了一组样本数据并对其进行了分析? 这可能不像你想象的那么糟糕。

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

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

这是解决scheme:

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

你可以使用正则expression式来代替string列表吗? 即使你不得不使用多个正则expression式,我认为testing几百(几百个)会比数千个string比较好。

如果速度至关重要,您可能需要为模式集寻找Aho-Corasickalgorithm 。

这是一个具有失败链接的树 ,即复杂度为O(n + m + k),其中n是input文本的长度,m是模式的累积长度,k是匹配的数量。 你只需要修改algorithm,find第一个匹配后终止。

 myList.Any(myString.Contains);