कैसे एक मनमाना हालत समारोह के अनुसार एक शब्दकोश फ़िल्टर करने के लिए?


212

मेरे पास अंकों का एक शब्दकोश है, कहते हैं:

>>> points={'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)}

मैं उन सभी बिंदुओं के साथ एक नया शब्दकोश बनाना चाहता हूं, जिसका x और y मान 5 से छोटा हो, यानी अंक 'a', 'b' और 'd'।

पुस्तक के अनुसार , प्रत्येक शब्दकोश में items()फ़ंक्शन होता है, जो (key, pair) टपल की सूची देता है :

>>> points.items()
[('a', (3, 4)), ('c', (5, 5)), ('b', (1, 2)), ('d', (3, 3))]

इसलिए मैंने यह लिखा है:

>>> for item in [i for i in points.items() if i[1][0]<5 and i[1][1]<5]:
...     points_small[item[0]]=item[1]
...
>>> points_small
{'a': (3, 4), 'b': (1, 2), 'd': (3, 3)}

वहाँ एक और अधिक सुंदर तरीका है? मैं पायथन से उम्मीद कर रहा था कि कुछ सुपर-कमाल का dictionary.filter(f)फंक्शन होगा ...


जवाबों:


427

आजकल, पायथन 2.7 और ऊपर में, आप एक तानाशाह की समझ का उपयोग कर सकते हैं:

{k: v for k, v in points.iteritems() if v[0] < 5 and v[1] < 5}

और पायथन 3 में:

{k: v for k, v in points.items() if v[0] < 5 and v[1] < 5}

15
वोट दें! यह मार्टेलिस की तुलना में दो गुना अधिक सामान्य दृष्टिकोण है। ध्यान दें कि आप विचारों का भी उपयोग कर सकते हैं (जैसे iteitems, वे तानाशाह वस्तुओं की नकल नहीं हैं): {k: v for k, v में points.viewitems () यदि v [0] <5 और v [1] < 5}
डोरवाक

5
और यहाँ एक अच्छी व्याख्या है कि क्यों फ़ंक्शन कॉल डिक्टेड () कंस्ट्रक्टर / शाब्दिक वाक्य रचना {} doughellmann.com/2012/11/…
dorvak

1
ध्यान रखें कि iteritemsअजगर 3 में हटा दिया गया था। लेकिन आप itemsइसके बजाय उपयोग कर सकते हैं । यह iteritemsपुराने संस्करणों में काम करने के तरीके का व्यवहार करता है।
एलियास ज़मरिया

1
@Datanovice मुझे यकीन है कि कोई भी हो सकता है। अधिक उपयोगी उत्तर प्राप्त करने के लिए पर्याप्त विस्तार के साथ एक नया प्रश्न भी खोल सकता है;)
थॉमस

1
एक ने सीमित प्रतिक्रियाओं के साथ एक प्रश्न खोला है, इस प्रकार एक ने एक बेहतर समझ प्राप्त करने के लिए जितने अधिक प्रश्नों को पढ़ने का सहारा लिया है। एक ने एक और जानकार को देखा और इस तरह, लोगों के दिमाग को जारी रखा;) मेरे क्यू: stackoverflow.com/questions/50104127/…
Datanovice

110
dict((k, v) for k, v in points.items() if all(x < 5 for x in v))

यदि आप Python 2 में हैं .iteritems(), .items()तो इसके बजाय आप कॉल करना चुन सकते हैं और बहुत सी प्रविष्टियाँ pointsहो सकती हैं ।

all(x < 5 for x in v)ओवरकिल हो सकता है यदि आप जानते हैं कि प्रत्येक बिंदु हमेशा 2 डी ही होगा (उस स्थिति में आप उसी बाधा को व्यक्त कर सकते हैं and) लेकिन यह ठीक काम करेगा ;-)


21
points_small = dict(filter(lambda (a,(b,c)): b<5 and c < 5, points.items()))

1
पायथन 2 में आइटम्स () के बजाय पुनरावृत्तियों () का उपयोग करें
Regisz

2
अजगर 3.5 में, यह एक त्रुटि देता है: points_small = तानाशाही (फ़िल्टर (लंबो ((बी, सी))): b <5 और c <5, points.items ()) ^ SyntaxError: अमान्य वाक्यविन्यास `
मेविन बाबू

मुझे लगता है कि यह अजगर 3 में समर्थित नहीं है
Matanster

15
>>> points = {'a': (3, 4), 'c': (5, 5), 'b': (1, 2), 'd': (3, 3)}
>>> dict(filter(lambda x: (x[1][0], x[1][1]) < (5, 5), points.items()))

{'a': (3, 4), 'b': (1, 2), 'd': (3, 3)}

3
महान ! गौरतलब है कि यह Py3 है, क्योंकि लंबोदर अब टपल तर्क को अनपैक नहीं कर सकते हैं ( PEP 3113 देखें )
Ciprian Tomoiagă

आप tuples की तुलना lexicographically से करते हैं, जो कि OP की आवश्यकता नहीं है। आपके मामले में, बिंदु (3, 10)परीक्षा पास करेगा: (3, 10) < (5, 5)यह सही है, लेकिन यह गलत है ( y5 से छोटा होना चाहिए)।
dmitry_romanov


7

मुझे लगता है कि एलेक्स मार्टेली का जवाब निश्चित रूप से ऐसा करने का सबसे सुरुचिपूर्ण तरीका है, लेकिन सिर्फ dictionary.filter(f)पाइथोनिक तरह से एक सुपर भयानक विधि के लिए अपनी इच्छा को संतुष्ट करने के लिए एक तरीका जोड़ना चाहता था :

class FilterDict(dict):
    def __init__(self, input_dict):
        for key, value in input_dict.iteritems():
            self[key] = value
    def filter(self, criteria):
        for key, value in self.items():
            if (criteria(value)):
                self.pop(key)

my_dict = FilterDict( {'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)} )
my_dict.filter(lambda x: x[0] < 5 and x[1] < 5)

मूल रूप से हम एक ऐसा वर्ग बनाते हैं जो इनहेरिट करता है dict, लेकिन फ़िल्टर विधि जोड़ता है। हमें .items()फ़िल्टरिंग के लिए उपयोग करने की आवश्यकता है , क्योंकि उपयोग .iteritems()करते समय विनाशकारी पुनरावृत्ति अपवाद को उठाएगी।


+1 धन्यवाद, सुरुचिपूर्ण कोड। मुझे वास्तव में लगता है कि यह मानक शब्दकोश का एक हिस्सा होना चाहिए।
एडम मटन

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