检查一个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);