जांचें कि क्या स्ट्रिंग में सूची से एक तत्व है (तार के)


155

कोड के निम्नलिखित ब्लॉक के लिए:

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

आउटपुट है:

मामला एक:

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

सूची (लिस्टऑफस्ट्रेस) में कई आइटम (न्यूनतम 20) हो सकते हैं और इसे हजारों स्ट्रिंग्स (जैसे मेरीस्ट्रिंग) के खिलाफ जांचना होगा।

क्या इस कोड को लिखने का एक बेहतर (अधिक कुशल) तरीका है?

जवाबों:


359

LINQ के साथ, और C # का उपयोग करके (मैं इन दिनों VB को ज्यादा नहीं जानता):

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

या (कम और अधिक कुशल, लेकिन यकीनन कम स्पष्ट):

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

यदि आप समानता का परीक्षण कर रहे थे, तो यह देखने लायक होगा HashSetआदि, लेकिन यह आंशिक मैचों के साथ मदद नहीं करेगा जब तक कि आप इसे टुकड़ों में विभाजित नहीं करते हैं और जटिलता का क्रम जोड़ते हैं।


अद्यतन: यदि आप वास्तव में "स्टार्टस्विथ" का अर्थ करते हैं, तो आप सूची को क्रमबद्ध कर सकते हैं और इसे एक सरणी में रख सकते हैं; फिर Array.BinarySearchप्रत्येक आइटम को खोजने के लिए उपयोग करें - देखने के लिए जाँच करके देखें कि यह पूर्ण या आंशिक मिलान है या नहीं।


1
इसके बजाय मैं उनके उदाहरणों के आधार पर स्टार्टस्विथ का उपयोग करूँगा।
tvanfosson

@tvanfosson - यह इस बात पर निर्भर करता है कि क्या उदाहरण पूरी तरह से समावेशी हैं, लेकिन हाँ, मैं सहमत हूँ। निश्चित रूप से बदलने के लिए सरल।
मार्क Gravell

एल्गोरिदम के स्तर पर यह कोड कितना अधिक कुशल है? यह छोटा और तेज़ है यदि "कोई" में लूप तेज़ हैं, लेकिन आपको कई बार सटीक मिलान करने वाली समस्या समान है।
टॉर्स्टन मारेक

यदि आप एक सेट का उपयोग कर रहे हैं तो आप एक कस्टम तुलनित्र सेटअप कर सकते हैं।
फेयरयुननर

अभ्यास में किसी भी औसत दर्जे के अंतर से दूसरा वास्तव में अधिक कुशल नहीं है।
ICR

7

जब आप अपने तार का निर्माण करते हैं तो यह इस तरह होना चाहिए

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

5

पहले के समान प्रश्न से कई सुझाव मिले थे " तुलनात्मक सूची की तुलना में मौजूदा स्ट्रिंग के लिए परीक्षण करने का सबसे अच्छा तरीका

आपकी आवश्यकता के लिए रेगेक्स पर्याप्त हो सकता है। अभिव्यक्ति उन सभी अभ्यर्थियों के बीच तालमेल बिठाती है, जिनके |बीच एक OR " " ऑपरेटर होता है। बेशक, आपको अभिव्यक्ति का निर्माण करते समय, या किसी जटिलता या आकार की सीमाओं के कारण इसे संकलित करने में विफलता के लिए बाहर के पात्रों को देखना होगा।

ऐसा करने का एक और तरीका सभी उम्मीदवार सबस्ट्रिंग का प्रतिनिधित्व करने के लिए एक त्रिकोणीय डेटा संरचना का निर्माण करना होगा (यह कुछ हद तक डुप्लिकेट हो सकता है कि रेगेक्स मैचर क्या कर रहा है)। जैसा कि आप परीक्षण स्ट्रिंग में प्रत्येक चरित्र के माध्यम से कदम रखते हैं, आप तीनों की जड़ में एक नया पॉइंटर बनाएंगे, और मौजूदा पॉइंटर्स को उपयुक्त बच्चे (यदि कोई हो) को आगे बढ़ाएंगे। आपको एक मैच मिलता है जब कोई पॉइंटर किसी पत्ते पर पहुंचता है।


5

मुझे मार्क का जवाब पसंद आया, लेकिन कॉन्स इनसेनसीटीवीवी होने के लिए कॉन्टेन्स के मिलान की आवश्यकता थी।

यह था हल:

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

यह नहीं होना चाहिए> -1?
CSharped

1
@CSharped>> -1 (माइनस 1 से अधिक) और> = 0 (शून्य के बराबर या अधिक) के समान कोई बात नहीं है।
WhoIsRich

2

आपके पैटर्न के आधार पर एक सुधार होगा जिसमें कॉन्टेंस के बजाय स्टार्टस्विथ का उपयोग करना होगा। प्रारंभ में प्रत्येक स्ट्रिंग के माध्यम से केवल इटर्स्ट की आवश्यकता होती है, जब तक कि वह हर वर्ण स्थिति में खोज को फिर से शुरू करने के बजाय पहला बेमेल पाता है जब वह एक पाता है।

इसके अलावा, आपके पैटर्न के आधार पर, ऐसा लगता है कि आप myString के लिए पथ के पहले भाग को निकालने में सक्षम हो सकते हैं, फिर तुलना को उल्टा कर सकते हैं - आसपास के अन्य तरीके के बजाय स्ट्रिंग्स की सूची में myString के शुरुआती पथ की तलाश कर रहे हैं।

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

return listOfStrings.Contains( startPath );

संपादित करें : यह भी तेजी से HashSet विचार @Marc Gravell का उल्लेख है जब से तुम को बदल सकता है का उपयोग करते हुए किया जाएगा Containsकरने के लिएContainsKey और देखने हे (एन) के हे (1) के बजाय होगा। आपको यह सुनिश्चित करना होगा कि रास्ते बिल्कुल मेल खाते हों। ध्यान दें कि यह @Marc Gravell का सामान्य समाधान नहीं है, लेकिन आपके उदाहरणों के अनुरूप है।

C # उदाहरण के लिए क्षमा करें। वीबी में अनुवाद करने के लिए मेरे पास पर्याप्त कॉफी नहीं थी।


पुनः शुरू होता है-साथ; शायद पूर्व-प्रकार और द्विआधारी खोज का उपयोग करें? यह फिर से तेज हो सकता है।
मार्क Gravell

2

पुराना सवाल। लेकिन चूँकि VB.NETमूल आवश्यकता थी। स्वीकृत उत्तर के समान मूल्यों का उपयोग करना:

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

1

क्या आपने गति का परीक्षण किया है?

यानी क्या आपने डेटा का एक नमूना सेट बनाया है और इसे प्रोफाइल किया है? यह उतना बुरा नहीं हो सकता जितना आप सोचते हैं।

यह कुछ ऐसा भी हो सकता है जिसे आप एक अलग धागे में बंद कर सकते हैं और गति का भ्रम दे सकते हैं!


0

यदि गति महत्वपूर्ण है, तो आप पैटर्न के सेट के लिए अहो-कोरसिक एल्गोरिथ्म की तलाश कर सकते हैं ।

यह विफलता लिंक के साथ एक तिकड़ी है , अर्थात, जटिलता हे (n + m + k), जहां n इनपुट पाठ की लंबाई है, पैटर्न की संचयी लंबाई और मैचों की संख्या k है। आपको पहला मैच मिलने के बाद समाप्त करने के लिए एल्गोरिथ्म को संशोधित करना होगा।



0

Containsविधि का दोष यह है कि यह तुलना प्रकार को निर्दिष्ट करने की अनुमति नहीं देता है जो अक्सर तार की तुलना करते समय महत्वपूर्ण होता है। यह हमेशा संस्कृति के प्रति संवेदनशील और मामले के प्रति संवेदनशील होता है। इसलिए मुझे लगता है कि WhoIsRich का उत्तर मूल्यवान है, मैं सिर्फ एक सरल विकल्प दिखाना चाहता हूं:

listOfStrings.Any(s => s.Equals(myString, StringComparison.OrdinalIgnoreCase))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.