उस सूची में ऑब्जेक्ट ढूंढें जिसमें कुछ मान के बराबर विशेषता है (जो किसी भी स्थिति को पूरा करता है)


221

मुझे वस्तुओं की सूची मिल गई है। मैं इस सूची में एक (पहली या जो भी) वस्तु ढूंढना चाहता हूं जिसमें विशेषता (या विधि परिणाम - जो भी हो) बराबर है value

इसे खोजने का सबसे अच्छा तरीका क्या है?

यहाँ परीक्षण मामला है:

  class Test:
      def __init__(self, value):
          self.value = value

  import random

  value = 5

  test_list = [Test(random.randint(0,100)) for x in range(1000)]

  # that I would do in Pascal, I don't believe isn't anywhere near 'Pythonic'
  for x in test_list:
      if x.value == value:
          print "i found it!"
          break

मुझे लगता है कि जनरेटर का उपयोग करना और reduce()इससे कोई फर्क नहीं पड़ेगा क्योंकि यह अभी भी सूची के माध्यम से पुनरावृत्त होगा।

ps: समीकरण valueकेवल एक उदाहरण है। निश्चित रूप से हम तत्व प्राप्त करना चाहते हैं जो किसी भी स्थिति को पूरा करता है।


2
यहाँ इस सवाल की एक अच्छी चर्चा है: tomayko.com/writings/cleanest-python-find-in-list-function
एंड्रयू हरे

मूल पोस्ट हास्यास्पद रूप से पुरानी है, लेकिन दूसरी प्रतिक्रिया मेरे एक-लाइन संस्करण से बिल्कुल मेल खाती है। मुझे यकीन नहीं है कि यह मूल लूप संस्करण की तुलना में बेहतर है।
18

जवाबों:


433
next((x for x in test_list if x.value == value), None)

यह उस सूची से पहला आइटम प्राप्त करता है जो शर्त से मेल खाता है, और Noneयदि कोई आइटम मेल नहीं खाता है तो वापस आ जाता है । यह मेरा पसंदीदा एकल-अभिव्यक्ति रूप है।

तथापि,

for x in test_list:
    if x.value == value:
        print "i found it!"
        break

भोले पाश-विराम संस्करण, पूरी तरह से पाइथोनिक है - यह संक्षिप्त, स्पष्ट और कुशल है। इसे वन-लाइनर के व्यवहार से मेल खाने के लिए:

for x in test_list:
    if x.value == value:
        print "i found it!"
        break
else:
    x = None

यह आवंटित करेगा Noneकरने के लिए xयदि आप नहीं breakलूप से बाहर।


72
"आश्वस्त करने के लिए +1" भोले पाश-विराम संस्करण, पूरी तरह से पाइथोनिक है "।
लॉन्ड्रोमैट

महान समाधान, लेकिन मैं आपकी लाइन को कैसे संशोधित करूं ताकि मैं x.value वास्तव में x.fieldMemberName का अर्थ बना सकूं जहां उस नाम को मूल्य में संग्रहीत किया गया है? फ़ील्ड = "नाम" अगला ((x in x_field = x मान के लिए x), कोई नहीं) ताकि इस मामले में, मैं वास्तव में x.name के खिलाफ जांच कर रहा हूं, न कि x.field
स्टीवर्ट डेल

3
@StewartDale यह पूरी तरह से स्पष्ट नहीं है कि आप क्या पूछ रहे हैं, लेकिन मुझे लगता है कि आपका मतलब है ... if getattr(x, x.fieldMemberName) == value। उस गुण को xसंग्रहीत नाम से लाया जाएगा fieldMemberName, और उसकी तुलना करेंगे value
एजीएफ़

1
@ThatTechGuy - elseखंड पर करने के लिए है for, पाश नहीं if। (अस्वीकृत संपादित करें)।
5

1
@agf वाह मुझे सचमुच कोई विचार नहीं था जो अस्तित्व में था .. book.pythontips.com/en/latest/for_-_else.html मस्त!
ThatTechGuy

25

चूंकि यह सिर्फ पूरा करने के लिए उल्लेख नहीं किया गया है। आपके तत्वों को फ़िल्टर करने के लिए अच्छा ol 'फ़िल्टर।

कार्यात्मक प्रोग्रामिंग ftw।

####### Set Up #######
class X:

    def __init__(self, val):
        self.val = val

elem = 5

my_unfiltered_list = [X(1), X(2), X(3), X(4), X(5), X(5), X(6)]

####### Set Up #######

### Filter one liner ### filter(lambda x: condition(x), some_list)
my_filter_iter = filter(lambda x: x.val == elem, my_unfiltered_list)
### Returns a flippin' iterator at least in Python 3.5 and that's what I'm on

print(next(my_filter_iter).val)
print(next(my_filter_iter).val)
print(next(my_filter_iter).val)

### [1, 2, 3, 4, 5, 5, 6] Will Return: ###
# 5
# 5
# Traceback (most recent call last):
#   File "C:\Users\mousavin\workspace\Scripts\test.py", line 22, in <module>
#     print(next(my_filter_iter).value)
# StopIteration


# You can do that None stuff or whatever at this point, if you don't like exceptions.

मुझे पता है कि आम तौर पर अजगर सूची समझ में पसंद किया जाता है या कम से कम वह है जो मैंने पढ़ा है, लेकिन मैं इस मुद्दे को ईमानदार नहीं देखता हूं। बेशक पायथन एफपी भाषा नहीं है, लेकिन मैप / रिड्यूस / फिल्टर पूरी तरह से पठनीय हैं और कार्यात्मक प्रोग्रामिंग में मानक उपयोग के मामलों के सबसे मानक हैं।

तो यह तूम गए वहाँ। अपनी कार्यात्मक प्रोग्रामिंग को जानें।

फ़िल्टर स्थिति सूची

इससे कोई आसान नहीं मिलेगा:

next(filter(lambda x: x.val == value,  my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions

मुझे इसकी शैली काफी पसंद है लेकिन दो संभावित मुद्दे हैं। 1 : यह केवल पायथन 3 में काम करता है; पायथन 2 में, filterएक सूची देता है जो संगत नहीं है next2 : इसके लिए आवश्यक है कि एक निश्चित मैच हो, अन्यथा आपको एक StopIterationअपवाद मिलेगा ।
freethebees

1
1: मैं अजगर 2 से अवगत नहीं हूँ। जब मैंने पायथन का उपयोग शुरू किया, तो पायथन 3 पहले से ही उपलब्ध था। दुर्भाग्य से मैं अजगर 2 के विनिर्देशनों के बारे में स्पष्ट नहीं हूँ। यदि आप अपवादों के प्रशंसक नहीं हैं, तो आप अगले (..., कोई नहीं) या कुछ अन्य डिफ़ॉल्ट मान का उपयोग कर सकते हैं। मैंने इसे अपने कोड में एक टिप्पणी के रूप में भी जोड़ा।
नीमा मौसवी

@freethebees प्वाइंट 2 वास्तव में अच्छा हो सकता है। जब मुझे किसी सूची में एक निश्चित वस्तु की आवश्यकता होती है, तो तेजी से असफल होना एक अच्छी बात है।
kap

7

एक सरल उदाहरण : हमारे पास निम्नलिखित सरणी है

li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]

अब, हम उस ऐरे में ऑब्जेक्ट ढूंढना चाहते हैं जिसकी आईडी 1 के बराबर है

  1. nextसूची समझ के साथ विधि का उपयोग करें
next(x for x in li if x["id"] == 1 )
  1. सूची समझ का उपयोग करें और पहले आइटम वापस करें
[x for x in li if x["id"] == 1 ][0]
  1. कस्टम फ़ंक्शन
def find(arr , id):
    for x in arr:
        if x["id"] == id:
            return x
find(li , 1)

उपरोक्त सभी विधियों का आउटपुट है {'id': 1, 'name': 'ronaldo'}


1

मैं बस एक ऐसी ही समस्या में भाग गया और उस मामले के लिए एक छोटा अनुकूलन तैयार किया जहां सूची में कोई भी वस्तु आवश्यकता को पूरा नहीं करती है। (मेरे उपयोग-मामले के कारण यह प्रमुख प्रदर्शन में सुधार हुआ):

सूची test_list के साथ, मैं एक अतिरिक्त सेट test_value_set रखता हूं जिसमें उस सूची के मान शामिल हैं जिन्हें मुझे फ़िल्टर करने की आवश्यकता है। इसलिए यहाँ एगफ के घोल का दूसरा भाग बहुत तेज़ हो जाता है।


1

आप ऐसा कुछ कर सकते हैं

dict = [{
   "id": 1,
   "name": "Doom Hammer"
 },
 {
    "id": 2,
    "name": "Rings ov Saturn"
 }
]

for x in dict:
  if x["id"] == 2:
    print(x["name"])

Thats क्या मैं वस्तुओं का एक लंबी सरणी में वस्तुओं को खोजने के लिए उपयोग करते हैं।


यह कैसे अलग है, जो प्रश्नकर्ता ने पहले ही कोशिश की है?
ओम् शेराज़

मैं यह दिखाना चाहता था कि कैसे वह वस्तुओं की श्रेणी और वस्तुओं को सरलतम तरीके से प्राप्त कर सकता है।
इल्यूड

0

आप __eq__अपनी Testकक्षा और उपयोग inऑपरेटर के लिए विधि के माध्यम से समृद्ध तुलना भी लागू कर सकते हैं । यकीन नहीं होता कि यह सबसे अच्छा स्टैंड-अलोन तरीका है, लेकिन अगर आपको कहीं और के Testआधार पर उदाहरणों की तुलना करने की आवश्यकता है value, तो यह उपयोगी हो सकता है।

class Test:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        """To implement 'in' operator"""
        # Comparing with int (assuming "value" is int)
        if isinstance(other, int):
            return self.value == other
        # Comparing with another Test object
        elif isinstance(other, Test):
            return self.value == other.value

import random

value = 5

test_list = [Test(random.randint(0,100)) for x in range(1000)]

if value in test_list:
    print "i found it"

0

नीचे दिए गए कोड के लिए, XGen एक स्वायत्त जनरेटर अभिव्यक्ति है, yFilt एक फ़िल्टर ऑब्जेक्ट है। ध्यान दें कि xGen के लिए जब सूची समाप्त हो जाती है तो StopIteration को फेंकने के बजाय अतिरिक्त कोई भी पैरामीटर वापस नहीं किया जाता है।

arr =((10,0), (11,1), (12,2), (13,2), (14,3))

value = 2
xGen = (x for x in arr if x[1] == value)
yFilt = filter(lambda x: x[1] == value, arr)
print(type(xGen))
print(type(yFilt))

for i in range(1,4):
    print('xGen: pass=',i,' result=',next(xGen,None))
    print('yFilt: pass=',i,' result=',next(yFilt))

आउटपुट:

<class 'generator'>
<class 'filter'>
xGen: pass= 1  result= (12, 2)
yFilt: pass= 1  result= (12, 2)
xGen: pass= 2  result= (13, 2)
yFilt: pass= 2  result= (13, 2)
xGen: pass= 3  result= None
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    print('yFilt: pass=',i,' result=',next(yFilt))
StopIteration
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.