पायथन: सूची में खोजें


583

मैं इस पार आया हूँ:

item = someSortOfSelection()
if item in myList:
    doMySpecialFunction(item)

लेकिन कभी-कभी यह मेरी सभी वस्तुओं के साथ काम नहीं करता है, जैसे कि उन्हें सूची में मान्यता प्राप्त नहीं थी (जब यह स्ट्रिंग की सूची है)।

क्या किसी सूची में आइटम खोजने का यह सबसे 'पायथोनिक' तरीका है if x in l::?


3
यह पूरी तरह से ठीक है और काम करना चाहिए अगर आइटम अंदर के तत्वों में से एक के बराबर है myList
निकल्स बी

1
क्या आपको लगता है कि यह चीजों को करने का अच्छा तरीका था? मेरे कई परीक्षणों में, शायद व्हाट्सएप था, और लाइन फीडिंग में अंतर करता था ... मैं बस यह सुनिश्चित करना चाहता था कि यह "सूची में मिल" (सामान्य रूप से) को लागू करने का अच्छा तरीका है
स्टीफन रोलैंड

जवाबों:


1173

जैसा कि आपके पहले प्रश्न के लिए: वह कोड पूरी तरह से ठीक है और काम करना चाहिए अगर itemअंदर के तत्वों में से एक के बराबर है myList। शायद तुम एक स्ट्रिंग है नहीं करता है खोजने की कोशिश बिल्कुल आइटम या हो सकता है आप एक नाव मूल्य जो अशुद्धि से ग्रस्त उपयोग कर रहे हैं में से एक से मेल खाते हैं।

आपके दूसरे प्रश्न के रूप में: यदि सूची में चीजों को "ढूंढ" लिया जाए तो वास्तव में कई संभावित तरीके हैं।

अगर कुछ अंदर है तो जाँच करना

यह वह उपयोग मामला है जिसका आप वर्णन करते हैं: यह जाँचना कि क्या किसी सूची के अंदर है या नहीं। जैसा कि आप जानते हैं, आप उसके लिए inऑपरेटर का उपयोग कर सकते हैं :

3 in [1, 2, 3] # => True

एक संग्रह को छानना

यही है, सभी तत्वों को एक अनुक्रम में खोजना जो एक निश्चित स्थिति को पूरा करते हैं। आप उसके लिए सूची की समझ या जनरेटर के भाव का उपयोग कर सकते हैं:

matches = [x for x in lst if fulfills_some_condition(x)]
matches = (x for x in lst if x > 6)

उत्तरार्द्ध एक जनरेटर लौटाएगा जिसे आप एक प्रकार की आलसी सूची के रूप में कल्पना कर सकते हैं जो केवल इसके माध्यम से पुनरावृति करते ही बनाया जाएगा। वैसे, पहले वाले के बराबर है

matches = filter(fulfills_some_condition, lst)

पायथन 2. यहाँ आप काम पर उच्च-क्रम के कार्य देख सकते हैं। पायथन 3 में, filterएक सूची नहीं लौटाता है, लेकिन एक जनरेटर जैसी वस्तु।

पहली घटना का पता लगाना

यदि आप केवल पहली चीज चाहते हैं जो एक शर्त से मेल खाती है (लेकिन आप नहीं जानते कि यह अभी तक क्या है), तो लूप के लिए उपयोग करना ठीक है (संभवतः elseक्लॉज का उपयोग करके , जो वास्तव में अच्छी तरह से ज्ञात नहीं है)। आप भी उपयोग कर सकते हैं

next(x for x in lst if ...)

जो पहला मैच लौटाएगा या StopIterationअगर कोई नहीं मिला तो उठाएगा । वैकल्पिक रूप से, आप उपयोग कर सकते हैं

next((x for x in lst if ...), [default value])

किसी वस्तु का स्थान खोजना

सूचियों के लिए, ऐसी indexविधि भी है जो कभी-कभी उपयोगी हो सकती है यदि आप जानना चाहते हैं कि सूची में एक निश्चित तत्व कहां है:

[1,2,3].index(2) # => 1
[1,2,3].index(4) # => ValueError

हालाँकि, ध्यान दें कि यदि आपके पास डुप्लिकेट है, तो .indexहमेशा सबसे कम इंडेक्स देता है: ......

[1,2,3,2].index(2) # => 1

यदि डुप्लिकेट हैं और आप सभी अनुक्रमित चाहते हैं तो आप enumerate()इसके बजाय उपयोग कर सकते हैं :

[i for i,x in enumerate([1,2,3,2]) if x==2] # => [1, 3]

10
स्टीफ़न: मुझे यह अलग तरीके से व्यक्त: if x in listहै नहीं बात यह है कि लोगों को एक में निर्मित समारोह नहीं किया जा रहा शिकायत करते हैं। वे इस तथ्य के बारे में शिकायत करते हैं कि किसी सूची में किसी चीज़ की पहली घटना को खोजने का कोई स्पष्ट तरीका नहीं है जो एक निश्चित स्थिति से मेल खाता है। लेकिन जैसा कि मेरे जवाब में कहा गया है, उसके next()लिए इस्तेमाल किया जा सकता है।
निकल्स बी।

3
@ स्टेफ़ेन: दूसरा एक टपल उत्पन्न नहीं करता है, लेकिन एक जनरेटर (जो कि एक अभी तक निर्मित सूची नहीं है, मूल रूप से)। यदि आप केवल एक बार परिणाम का उपयोग करना चाहते हैं, तो एक जनरेटर आमतौर पर बेहतर होता है। हालांकि, यदि आप बाद में कई बार बनाए गए संग्रह का उपयोग करना चाहते हैं, तो पहली जगह में एक स्पष्ट सूची बनाना उचित है। मेरे अपडेट पर एक नज़र डालें, यह अब थोड़ा बेहतर संरचित है :)
निकल्स बी

26
आपकी "पहली घटना का पता लगाना" उदाहरण सुनहरा है। [list comprehension...][0]दृष्टिकोण की तुलना में अधिक
पायथोनिक

4
मैं अजगर 'कार्यात्मक' क्षमताओं के साथ अधिक से अधिक असंतुष्ट हूं। हैस्केल में Data.List मॉड्यूल में फ़ंक्शन पाया जाता है जो वास्तव में ऐसा कर रहा है। लेकिन अजगर में यह नहीं है और यह एक पुस्तकालय बनाने के लिए छोटा है, इसलिए आपको एक ही तर्क को बार-बार लागू करना होगा। क्या बर्बादी ...
user1685095

3
यह अच्छा होगा अगर वहाँ एक kwarg index()कहा जाता है keyकि keyद्वारा स्वीकृत की तरह काम किया max(); उदाहरण के लिए: index(list, key=is_prime)
कर्ट

189

यदि आप एक तत्व ढूंढना चाहते हैं या Noneडिफ़ॉल्ट रूप से उपयोग करना चाहते हैं next, तो यह तब नहीं बढ़ेगा StopIterationजब सूची में आइटम नहीं मिला:

first_or_default = next((x for x in lst if ...), None)

1
nextपहले पैरामीटर के रूप में एक पुनरावृत्ति लेता है और एक सूची / टपल नहीं है। तो इसे docs.python.org/3/library/functions.html#nextfirst_or_default = next(iter([x for x in lst if ...]), None)
Devy

7
@Devy: सही है, लेकिन यह है कि (x for x in lst if ...)सूची पर एक जनरेटर है lst(जो है पुनरावर्तक)। यदि आप करते हैं next(iter([x for x in lst if ...]), None), तो आपको सूची का निर्माण करना [x for x in lst if ...]होगा, जो एक बहुत अधिक महंगा ऑपरेशन होगा।
एर्लेंड ग्रेफ

1
एक खोज समारोह को परिभाषित करने के लिए यहां एक अमूर्तता है। बस ifएक मेमने में बूलियन के समापन को समझाया और आप find(fn,list)जनरेटर कोड को बाधित करने के बजाय आमतौर पर लिख सकते हैं ।
सेमीोमैंट

22

हालांकि निकल्स बी का जवाब बहुत व्यापक है, जब हम किसी सूची में एक आइटम खोजना चाहते हैं तो यह कभी-कभी इसका सूचकांक प्राप्त करने के लिए उपयोगी होता है:

next((i for i, x in enumerate(lst) if [condition on x]), [default value])

11

पहली घटना का पता लगाना

इसके लिए एक नुस्खा है itertools:

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)

उदाहरण के लिए, निम्न कोड सूची में पहला विषम संख्या पाता है:

>>> first_true([2,3,4,5], None, lambda x: x%2==1)
3  

6

एक अन्य विकल्प: आप जांच सकते हैं कि कोई आइटम किसी सूची में है या नहीं if item in list:, लेकिन यह ऑर्डर O (n) है। यदि आप वस्तुओं की बड़ी सूचियों के साथ काम कर रहे हैं और आपको यह जानने की जरूरत है कि क्या कुछ आपकी सूची का सदस्य है, तो आप सूची को पहले सेट में बदल सकते हैं और निरंतर समय सेट लुकअप का लाभ उठा सकते हैं :

my_set = set(my_list)
if item in my_set:  # much faster on average than using a list
    # do something

हर मामले में सही समाधान नहीं हो सकता है, लेकिन कुछ मामलों के लिए यह आपको बेहतर प्रदर्शन दे सकता है।

ध्यान दें कि सेट को बनाना set(my_list)भी O (n) है, इसलिए यदि आपको केवल एक बार ऐसा करने की आवश्यकता है तो इसे इस तरह से करना कोई तेज़ नहीं है। यदि आपको सदस्यता की बार-बार जांच करने की आवश्यकता है, तो यह उस प्रारंभिक सेट के निर्माण के बाद प्रत्येक लुकअप के लिए O (1) होगा।


4

तार की सूची के साथ काम करते समय आप दो संभावित खोजों में से एक का उपयोग करना चाह सकते हैं:

  1. यदि सूची तत्व एक आइटम के बराबर है ('उदाहरण' ['एक', 'उदाहरण', 'दो']) में है:

    if item in your_list: some_function_on_true()

    'पूर्व' में ['एक', 'पूर्व', 'दो'] => सत्य

    'ex_1' में ['one', 'ex', 'two'] => गलत

  2. यदि सूची तत्व एक आइटम की तरह है ('पूर्व' ['एक,' उदाहरण ',' दो '] या' example_1 'में [' एक ',' उदाहरण ',' दो ') में है:

    matches = [el for el in your_list if item in el]

    या

    matches = [el for el in your_list if el in item]

    फिर len(matches)जरूरत पड़ने पर बस उन्हें जांचें या पढ़ें।


3

परिभाषा और उपयोग

count()विधि निर्दिष्ट मान के साथ तत्वों की संख्या देता है।

वाक्य - विन्यास

list.count(value)

उदाहरण:

fruits = ['apple', 'banana', 'cherry']

x = fruits.count("cherry")

प्रश्न का उदाहरण:

item = someSortOfSelection()

if myList.count(item) >= 1 :

    doMySpecialFunction(item)

2
क्या यह बहुत लंबी सूची में कुशल है? एक लाख की सूची कहें?
3kstc

1
मुझे यकीन नहीं है !!!
जॉज डेफ

1

इसका उपयोग करने के बजाय list.index(x)जो x का इंडेक्स सूची में पाया जाता है या एक #ValueErrorसंदेश देता है यदि एक्स नहीं मिला है, तो आप उपयोग कर सकते हैं list.count(x)जो सूची में x के होने की संख्या लौटाता है (सत्यापन कि x वास्तव में सूची में है) या यह रिटर्न 0 अन्यथा (एक्स की अनुपस्थिति में)। इसके बारे count()में अच्छी बात यह है कि यह आपके कोड को नहीं तोड़ता है या जब एक्स नहीं मिलता है तो आपको अपवाद को फेंकने की आवश्यकता होती है


और बुरी बात यह है कि यह तत्वों को गिनता है। तत्व मिलने पर यह रुकता नहीं है। इसलिए प्रदर्शन बड़ा सूचियों पर बुरा है
जीन फ़्राँस्वा Fabre

1

यदि आप जाँचने जा रहे हैं कि क्या मूल्य संग्रहणीय में एक बार मौजूद है तो 'इन' ऑपरेटर का उपयोग करना ठीक है। हालांकि, यदि आप एक से अधिक बार जांच करने जा रहे हैं तो मैं बिज़ेक्ट मॉड्यूल का उपयोग करने की सलाह देता हूं। ध्यान रखें कि बाइसेक्ट मॉड्यूल डेटा का उपयोग करना चाहिए। तो आप एक बार डेटा सॉर्ट करें और फिर आप बाइसेक्ट का उपयोग कर सकते हैं। मेरी मशीन पर बाइसेक्ट मॉड्यूल का उपयोग करना 'ऑपरेटर' में उपयोग करने की तुलना में लगभग 12 गुना तेज है।

यहाँ पायथन 3.8 और सिंटैक्स के ऊपर कोड का एक उदाहरण दिया गया है:

import bisect
from timeit import timeit

def bisect_search(container, value):
    return (
      (index := bisect.bisect_left(container, value)) < len(container) 
      and container[index] == value
    )

data = list(range(1000))
# value to search
true_value = 666
false_value = 66666

# times to test
ttt = 1000

print(f"{bisect_search(data, true_value)=} {bisect_search(data, false_value)=}")

t1 = timeit(lambda: true_value in data, number=ttt)
t2 = timeit(lambda: bisect_search(data, true_value), number=ttt)

print("Performance:", f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")

आउटपुट:

bisect_search(data, true_value)=True bisect_search(data, false_value)=False
Performance: t1=0.0220, t2=0.0019, diffs t1/t2=11.71

0

जांचें कि स्ट्रिंग की सूची के आइटम में कोई अतिरिक्त / अवांछित श्वेत स्थान नहीं है। यह एक कारण है कि वस्तुओं को समझाने के लिए हस्तक्षेप नहीं किया जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.