पायथन में वस्तुओं की सूची खोजना


93

मान लेते हैं कि मैं केवल डेटा तत्वों को रखने के लिए सी-स्टाइल संरचना के समान काम करने के लिए एक साधारण वर्ग बना रहा हूं। मैं यह पता लगाने की कोशिश कर रहा हूं कि एक निश्चित मूल्य के बराबर की विशेषता वाली वस्तुओं के लिए वस्तुओं की एक सूची कैसे खोजें। नीचे एक तुच्छ उदाहरण दिया गया है कि मैं क्या करने की कोशिश कर रहा हूं।

उदाहरण के लिए:

class Data:
    pass

myList = []

for i in range(20):
    data = Data()
    data.n = i
    data.n_squared = i * i
    myList.append(data)

मैं यह निर्धारित करने के लिए myList सूची की खोज कैसे करूँगा कि क्या इसमें n == 5 वाला तत्व है?

मैं Googling और पायथन डॉक्स की खोज कर रहा हूं, और मुझे लगता है कि मैं यह एक सूची समझ के साथ कर सकता हूं, लेकिन मुझे यकीन नहीं है। मैं जोड़ सकता हूं कि मैं अजगर 2.4.3 का उपयोग कर रहा हूं, इसलिए कोई भी नया gee-whiz 2.6 या 3.x विशेषताएं मेरे लिए उपलब्ध नहीं हैं।


शायद आपके उदाहरण का एक अनजाना क्विक: myList = [Data ()। N == 0, Data ()। N = 1, ...] जहां data.n को रेंज () और data.n द्वारा असाइन किया जाएगा। myList में अनुक्रमणिका। इसलिए आपको केवल सूचकांक मान द्वारा myList को संदर्भित करके किसी भी डेटा () उदाहरण को खींचने की अनुमति देता है। बेशक आप बाद में modifiy myList [0] .n = 5.2 या कुछ और कर सकते हैं। और उदाहरण शायद अति-सरलीकृत था।
— DevPlayer

जवाबों:


138

आप सूची मिलान के साथ सभी मिलान तत्वों की एक सूची प्राप्त कर सकते हैं :

[x for x in myList if x.n == 30]  # list of all elements with .n==30

यदि आप बस यह निर्धारित करना चाहते हैं कि सूची में कोई तत्व है जो मेल खाता है और इसे (अपेक्षाकृत) कुशलता से करता है, तो आप कर सकते हैं

def contains(list, filter):
    for x in list:
        if filter(x):
            return True
    return False

if contains(myList, lambda x: x.n == 3)  # True if any element has .n==3
    # do stuff

25
या, myList में x के लिए कोई भी (custom_filter (x) अगर xn == 30) जो कि आपके "" सम्‍मिलित "कार्य को एक बेसिन के रूप में करता है।
— nosklo

Nosklo पर सिंटैक्स त्रुटि - जनरेटर के चारों ओर () का एक अतिरिक्त सेट की आवश्यकता है।
— गहूआ

ऐसा नहीं। यह कोशिश करो और देखो।
— रॉबर्ट रॉसनी

1
इस उत्तर को गहुआ के साथ मिलकर करना अच्छा होगा ( stackoverflow.com/a/598602/2349262 )।
— रोमन ह्वांग

77

सरल, सुरुचिपूर्ण और शक्तिशाली:

एक बिलियन के साथ संयोजन में एक जनरेटर अभिव्यक्ति ... (अजगर 2.5+)

any(x for x in mylist if x.n == 10)

पायथन any()बिल्डिन का उपयोग करता है , जिसे निम्नानुसार परिभाषित किया गया है:

-> यदि कोई पुनरावृति का कोई भी तत्व सत्य है, तो (पुनरावृत्ति) सही है। के बराबर:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

अच्छा लगा। FYI करें आप कुछ पार्न्स (भी = = नहीं =) को बचाने के लिए x (myn अगर xn == 10 में x के लिए x) कर सकते हैं।
— जैकब गेब्रियलसन

मैं उपयोग करना पसंद करता हूं any(x for x in mylist if x['n'] == 10)लेकिन अच्छा विचार है
— एलेक्स मोंटोया

47

पूर्णता के लिए, आइए सरल कार्य को न भूलें जो संभवतः कार्य कर सकते हैं:

for i in list:
  if i.n == 5:
     # do something with it
     print "YAY! Found one!"

39
[x for x in myList if x.n == 30]               # list of all matches
[x.n_squared for x in myList if x.n == 30]     # property of matches
any(x.n == 30 for x in myList)                 # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30]  # indices of all matches

def first(iterable, default=None):
  for item in iterable:
    return item
  return default

first(x for x in myList if x.n == 30)          # the first match, if any

1
यह "पहले" विधि के कारण एक अच्छा जवाब है, जो संभवतः सबसे आम उपयोग का मामला है।
— गैलेंट्रन

बहुत धन्यवाद! मैच सूचकांकों के लिए मैं क्या देख रहा था। क्या किसी अन्य फ़ील्ड तक पहुँचने के लिए सूची को सीधे अनुक्रमित करने के लिए इसका उपयोग करने का कोई शॉर्टकट है? अब मुझे सूची प्रविष्टियों की एक सूची मिलती है (केवल एक प्रविष्टि है, इसलिए यह एक आइटम के साथ एक सूची है)। सूचकांक प्राप्त करने के लिए, मुझे सूची को अनुक्रमित करने के लिए उपयोग करने से पहले [0] परिणाम करने की आवश्यकता है। प्रश्न के उदाहरण से, मैं एक विशेष n से n_squared का उपयोग करना चाहता हूं: myList [myList.n == 5] का सूचकांक .n_squared
— फ्रीके

31
filter(lambda x: x.n == 5, myList)

25
जो कोई अजगर सीखना चाहता है, उसके लिए मेमना समझना बुनियादी है।
— वार्टेक

2
ठीक है, हाँ और नहीं - सूची की समझ और ऑपरेटर जैसे महत्वपूर्ण कार्य निर्माताओं को छाँटने के साथ। मतदाता, मैं शायद ही कभी lambdaएस का उपयोग करता हूं ।
— बेन होयट

9

आप inएक संग्रह में एक आइटम के लिए देखने के लिए उपयोग कर सकते हैं , और जिस क्षेत्र में आप रुचि रखते हैं उसे निकालने के लिए एक सूची समझ। यह (सूचियों, सेट, ट्यूपल्स और कुछ भी जो परिभाषित करता है __contains__या __getitem__) के लिए काम करता है ।

if 5 in [data.n for data in myList]:
    print "Found it"

यह सभी देखें:


4

आपको अपनी कक्षा में एक __eq__और एक __hash__विधि जोड़ना चाहिए Data, यह जाँच सकता है कि क्या__dict__ विशेषताएँ समान (समान गुण) हैं और फिर यदि उनके मान समान हैं, तो भी।

यदि आपने ऐसा किया है, तो आप उपयोग कर सकते हैं

test = Data()
test.n = 5

found = test in myList

inकीवर्ड जांच करता है कि testमें हैmyList ।

यदि आप केवल आप nमें संपत्ति का Dataउपयोग करना चाहते हैं:

class Data(object):
    __slots__ = ['n']
    def __init__(self, n):
        self.n = n
    def __eq__(self, other):
        if not isinstance(other, Data):
            return False
        if self.n != other.n:
            return False
        return True
    def __hash__(self):
        return self.n

    myList = [ Data(1), Data(2), Data(3) ]
    Data(2) in myList  #==> True
    Data(5) in myList  #==> False

3

एक शब्दकोष का उपयोग करने पर विचार करें:

myDict = {}

for i in range(20):
    myDict[i] = i * i

print(5 in myDict)

या: d = तानाशाही (i, i * i) i के लिए i in रेंज (20))
— hughdbrown

यह मेरे प्रश्न का वर्णन करने के लिए इस्तेमाल की गई तुच्छ समस्या को हल करता है, लेकिन वास्तव में मेरे मूल प्रश्न को हल नहीं करता है। मैं जो उत्तर खोज रहा था (5+ साल पहले) वह सूची बोध था। :)
— m0j0

1

दूसरा तरीका जो आप कर सकते हैं वह है अगला () फ़ंक्शन का उपयोग करना।

matched_obj = next(x for x in list if x.n == 10)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.