2011-12-21 14 views
22

संभव डुप्लिकेट:
Check if multiple strings exist in another stringकैसे जांचें कि किसी पंक्ति में किसी सूची में तारों में से एक है या नहीं?

मैं अगर वहाँ 3 अलग स्ट्रिंग्स के लिए परीक्षण करने के लिए एक अच्छा और साफ तरीका है पता लगाने के लिए कोशिश कर रहा हूँ।

असल में मैं for लूप का उपयोग कर एक फ़ाइल को लूप कर रहा हूं; तो मुझे यह जांचना होगा कि इसमें एक सूची में सेट किए गए 3 तारों में से 1 है या नहीं।

अब तक मैं बहुत से अगर हालत की जांच में पाया गया है, लेकिन यह महसूस नहीं करता है की तरह वास्तव में सुंदर और कुशल है:

for line in file 
    if "string1" in line or "string2" in line or "string3" in line: 
     print "found the string" 

मैं एक सूची है कि string1, string2 और string3 शामिल बनाने की तरह सोच रहा था, और जांचें कि इनमें से कोई भी लाइन में निहित है, लेकिन ऐसा नहीं लगता है कि मैं सूची की तुलना केवल सूची की तुलना में सूची की तुलना कर सकता हूं, और उस स्थिति में मैं मूल रूप से उसी स्थिति में हूं जैसे कि कथन I ऊपर लिखा है।

क्या बयान या लूप सूची के तत्वों को कम करने के लिए लंबे समय तक लिखने के बिना कई तारों के खिलाफ जांच करने का कोई स्मार्ट तरीका है?

+0

क्या आपको हर पंक्ति को खोजने की ज़रूरत है या सिर्फ पहले को ढूंढना है? यदि ऐसा है, तो आप लूप के बाहर तोड़कर अनुकूलित कर सकते हैं। –

उत्तर

56
strings = ("string1", "string2", "string3") 
for line in file: 
    if any(s in line for s in strings): 
     print "yay!" 
+2

जबकि ['any'] (http://docs.python.org/library/functions.html?highlight=any#any) का अर्थ बहुत तार्किक है, मैंने कभी इसका उपयोग नहीं किया है इसलिए मुझे इसे देखना पड़ा । अच्छा कोड @ निकलास। – FakeRainBrigand

+0

यह लगभग उसी तरह से व्यवहार करता है। –

+3

यह एक समारोह है। सभी 'कोई भी' जांच करता है कि अनुक्रम में कोई भी मान सत्य है- ish। वास्तविक जादू अनुक्रम के लिए जनरेटर अभिव्यक्ति का उपयोग कर रहा है। –

10

यह अभी भी दो सूचियों की कार्तीय उत्पाद के माध्यम से लूप होता है, लेकिन यह यह एक पंक्ति है:

>>> lines1 = ['soup', 'butter', 'venison'] 
>>> lines2 = ['prune', 'rye', 'turkey'] 
>>> search_strings = ['a', 'b', 'c'] 
>>> any(s in l for l in lines1 for s in search_strings) 
True 
>>> any(s in l for l in lines2 for s in search_strings) 
False 

यह भी है लाभ any शॉर्ट सर्किट, और इसलिए पाशन के रूप में बंद हो जाता है कि जैसे ही एक मैच मिल जाता है। इसके अलावा, यह linesX में search_strings से स्ट्रिंग की पहली घटना को केवल पाता है। आप कुछ इस तरह कर सकता है आप एक से अधिक घटनाओं को खोजने के लिए चाहते हैं:

>>> lines3 = ['corn', 'butter', 'apples'] 
>>> [(s, l) for l in lines3 for s in search_strings if s in l] 
[('c', 'corn'), ('b', 'butter'), ('a', 'apples')] 

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

+1

असल में वहाँ है। अहो-कोरासिक automaton देखें। यह रैखिक समय –

+0

@NiklasB में किया जा सकता है। धन्यवाद, यह काफी रोचक है! अगर मैं गलत हूं तो मुझे सही करें, लेकिन मुझे लगता है कि परिणाम अभी भी वर्गबद्ध होगा, क्योंकि ओपी सबस्ट्रिंग मैचों के लिए कई लाइनों का परीक्षण करना चाहता है। लेकिन यह अभी भी बेवकूफ 'किसी भी संस्करण' (क्यूबिक, 'इन' के औसत ओ (एन) प्रदर्शन मानते हैं)। – senderle

+0

नहीं यह रैखिक है। आटोमैटिक मशीन बिल्डिंग रैखिक समय और आटोमैटिक मशीन में एक स्ट्रिंग खिला है –

3

एक दृष्टिकोण खोज स्ट्रिंग को रेगेक्स पैटर्न में this answer में जोड़ना है।

+0

मैं एक regex लगता है सुंदर है, लेकिन regex काफी overhead है नहीं है? क्या यह वास्तव में एक सरल 'अगर ... या ... या ...:' से अधिक कुशल हो सकता है? –

+0

@ सैमरेडवे कुछ ओवरहेड है, लेकिन दूसरी तरफ सर्च स्ट्रिंग को एक पैटर्न में जोड़ा जा सकता है जिसे "एक बार में" संसाधित किया जाता है। –

+0

@ सैमरेडवे हम्म ठीक है, एक त्वरित परीक्षण –

संबंधित मुद्दे

 संबंधित मुद्दे