对于以下代码块:
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)进行检查。
是否有更好(更有效)的方法来编写此代码?
答案 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())
不区分大小写的 myString
和 listOfStrings
已转换为大写。