[英]Check if a string contains an element from a list (of strings)
對於以下代碼塊:
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)進行檢查。
有沒有更好(更有效)的方式來編寫這段代碼?
使用 LINQ,並使用 C#(這些天我不太了解 VB):
bool b = listOfStrings.Any(s=>myString.Contains(s));
或(更短、更高效,但可能不太清楚):
bool b = listOfStrings.Any(myString.Contains);
如果您正在測試相等性,則值得查看HashSet
等,但這對部分匹配無濟於事,除非您將其拆分為片段並添加復雜性。
更新:如果您的意思是“StartsWith”,那么您可以對列表進行排序並將其放入一個數組中; 然后使用Array.BinarySearch
查找每個項目 - 通過查找檢查它是完全匹配還是部分匹配。
當你構造你的字符串時,它應該是這樣的
bool inact = new string[] { "SUSPENDARE", "DIZOLVARE" }.Any(s=>stare.Contains(s));
我喜歡 Marc 的回答,但需要包含匹配才能成為 CaSe InSenSiTiVe。
這是解決方案:
bool b = listOfStrings.Any(s => myString.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0))
早期的類似問題“ 針對大量可比較項測試現有字符串的最佳方法”提出了許多建議。
正則表達式可能足以滿足您的要求。 該表達式將是所有候選子字符串的串聯,在它們之間使用 OR “ |
” 運算符。 當然,您在構建表達式時必須注意未轉義的字符,或者由於復雜性或大小限制而導致編譯失敗。
另一種方法是構造一個trie 數據結構來表示所有候選子字符串(這可能會復制正則表達式匹配器正在做的事情)。 當您逐步遍歷測試字符串中的每個字符時,您將創建一個指向特里樹根的新指針,並將現有指針前進到適當的子節點(如果有)。 當任何指針到達葉子時,您會得到匹配項。
老問題。 但由於VB.NET
是最初的要求。 使用已接受答案的相同值:
listOfStrings.Any(Function(s) myString.Contains(s))
根據您的模式,一項改進是改為使用 StartsWith 而不是包含。 StartsWith 只需要遍歷每個字符串,直到找到第一個不匹配項,而不必在找到每個字符位置重新開始搜索。
此外,根據您的模式,您似乎可以提取 myString 路徑的第一部分,然后反轉比較——在字符串列表中查找 myString 的起始路徑,而不是相反。
string[] pathComponents = myString.Split( Path.DirectorySeparatorChar );
string startPath = pathComponents[0] + Path.DirectorySeparatorChar;
return listOfStrings.Contains( startPath );
編輯:使用@Marc Gravell 提到的 HashSet 想法會更快,因為您可以將Contains
更改為ContainsKey
並且查找將是 O(1) 而不是 O(N)。 您必須確保路徑完全匹配。 請注意,這不是@Marc Gravell 的通用解決方案,而是針對您的示例量身定制的。
對不起 C# 示例。 我還沒有喝足夠的咖啡來翻譯成 VB。
我不確定它是否更有效,但您可以考慮在Lambda Expressions中使用它 。
你測試過速度嗎?
即您是否創建了一組樣本數據並對其進行了分析? 它可能沒有你想象的那么糟糕。
這也可能是你可以產生到一個單獨的線程並給人一種速度錯覺的東西!
myList.Any(myString.Contains);
如果速度很重要,您可能需要為模式集尋找Aho-Corasick 算法。
這是一個帶有失敗鏈接的嘗試,即復雜度為 O(n+m+k),其中 n 是輸入文本的長度,m 是模式的累積長度,k 是匹配的數量。 您只需要修改算法以在找到第一個匹配項后終止。
Contains
方法的缺點是它不允許指定比較類型,這在比較字符串時通常很重要。 它始終區分文化和大小寫。 所以我認為 WhoIsRich 的回答很有價值,我只想展示一個更簡單的替代方案:
listOfStrings.Any(s => s.Equals(myString, StringComparison.OrdinalIgnoreCase))
因為我需要檢查(長)字符串中的列表中是否有項目,所以我最終得到了這個:
listOfStrings.Any(x => myString.ToUpper().Contains(x.ToUpper()));
或者在 vb.net 中:
listOfStrings.Any(Function(x) myString.ToUpper().Contains(x.ToUpper()))
略有變化,我需要找出字符串中是否有完整的單詞和不區分大小寫的。
myString.Split(' ', StringSplitOptions.RemoveEmptyEntries).Intersect(listOfStrings).Any())
對於不區分大小寫的myString
和listOfStrings
已轉換為大寫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.