एक अजगर शब्दकोश में फ़िल्टर आइटम जहां कुंजियों में एक विशिष्ट स्ट्रिंग होती है


97

मैं एक सी कोडर हूं जो अजगर में कुछ विकसित कर रहा है। मुझे पता है कि सी में निम्नलिखित कैसे करना है (और इसलिए सी-जैसे तर्क में अजगर पर लागू होता है), लेकिन मैं सोच रहा हूं कि यह करने का 'पायथन' तरीका क्या है।

मेरे पास एक डिक्शनरी है, और मैं वस्तुओं के सबसेट पर काम करना चाहूंगा, केवल उन लोगों की कुंजी (स्ट्रिंग) में एक विशिष्ट विकल्प है।

यानी सी लॉजिक होगा:

for key in d:
    if filter_string in key:
        # do something
    else
        # do nothing, continue

मैं कल्पना कर रहा हूं कि अजगर संस्करण कुछ ऐसा होगा

filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
    # do something

मैंने यहाँ पर शब्दकोशों को फ़िल्टर करने के बारे में बहुत सारे पोस्ट पाए हैं, लेकिन एक ऐसा नहीं मिला जो इसमें शामिल हो।

मेरी डिक्शनरी नेस्टेड नहीं है और मैं अजगर 2.7 का उपयोग कर रहा हूं



जवाबों:


188

कैसे एक व्यापक समझ के बारे में :

filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}

आप इसे देख रहे हैं, यह आत्म-व्याख्यात्मक होना चाहिए, क्योंकि यह अंग्रेजी की तरह अच्छी तरह से पढ़ता है।

इस सिंटैक्स को पाइथन 2.7 या अधिक की आवश्यकता होती है।

पायथन 3 में, केवल है dict.items(), iteritems()इसलिए आप उपयोग नहीं करेंगे:

filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}

1
क्यों नहीं filtered_dict = {k:d[k] for k in d if filter_string in k}?
thefourtheye

5
@thefourtheye मुझे लगता है कि मेरा तेजी से हो रहा है, क्योंकि यह d[k]लुकअप नहीं करता है ।
जोनाथन रेनहार्ट

इसके अलावा, वह # do somethingटिप्पणियों में कहते हैं , लेकिन हम यहां कुछ चाबियाँ छोड़ देते हैं।
thefourtheye

क्या हमारे पास iteritemsपायथन 3 है? मुझे ऐसा नहीं लगता। तो, मेरा संस्करण संगत होगा, नहीं?
thefourtheye

1
पायथन 3 में, आप के iteritemsसाथ प्रतिस्थापित करेंगे items, जो कि पायथन 2.7 के समान है iteritems
जोनाथन रेनहार्ट

18

सबसे पठनीय और आसानी से बनाए रखने योग्य है। सिर्फ इसलिए कि आप इसे एक पंक्ति में लिख सकते हैं इसका मतलब यह नहीं है कि आपको चाहिए। आपका मौजूदा समाधान इस बात के करीब है कि मैं मान के लुक को छोड़ने के लिए उपयोगकर्ता पुनरावृत्तियों के अलावा अन्य उपयोग क्या करूंगा, और अगर मैं उनसे बच सकता हूं तो मुझे नीडिंत से नफरत है:

for key, val in d.iteritems():
    if filter_string not in key:
        continue
    # do something

हालाँकि यदि आप किसी चीज़ को फ़िल्टर किए गए डिक्टेट के माध्यम से पुनरावृत्त होने देना चाहते हैं, तो मैं फ़िल्टर्ड तानाशाही के निर्माण की दो चरणीय प्रक्रिया नहीं करूँगा और फिर इसके माध्यम से पुनरावृत्ति करूँगा, लेकिन इसके बजाय एक जनरेटर का उपयोग करें, क्योंकि इससे अधिक पायथोनिक (और भयानक) क्या है एक जनरेटर

सबसे पहले हम अपना जनरेटर बनाते हैं, और अच्छा डिज़ाइन तय करता है कि हम इसे पुन: प्रयोज्य होने के लिए पर्याप्त रूप से बनाते हैं:

# The implementation of my generator may look vaguely familiar, no?
def filter_dict(d, filter_string):
    for key, val in d.iteritems():
        if filter_string not in key:
            continue
        yield key, val

और फिर हम आपकी समस्या को हल करने के लिए जनरेटर का उपयोग कर सकते हैं और सरल, समझदार कोड के साथ सफाई से:

for key, val in filter_dict(d, some_string):
    # do something

संक्षेप में: जनरेटर बहुत बढ़िया हैं।


11

आप विशिष्ट परिस्थितियों के आधार पर शब्दकोशों, सूचियों आदि को फ़िल्टर करने के लिए अंतर्निहित फ़िल्टर फ़ंक्शन का उपयोग कर सकते हैं।

filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))

लाभ यह है कि आप इसे विभिन्न डेटा संरचनाओं के लिए उपयोग कर सकते हैं।


ध्यान दें कि लंबोदर परिभाषा में items:होना चाहिए item:
bkribbs

त्रुटि को इंगित करने के लिए @bkribbs को धन्यवाद। मैंने इसे अब ठीक कर दिया है।
पुलकित

8
input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}

3
मेरी विधि का उपयोग iteritems()करने की तुलना में अधिक कुशल होने जा रहा है items()
जोनाथन रेनहार्ट

@Jonathin Reinhart मुझे इसके बारे में पता नहीं था। धन्यवाद।
jspurim

2
केवल पायथन 2.7 पर। पाइथन 3 में केवल वही है items() , जो पाइथन 2.7 की तरह काम करता है iteritems
जोनाथन रेनहार्ट

1
प्रश्न स्पष्ट रूप से अजगर के लिए 2.7 है
ब्रेंडन एफ

7

जोनाथन ने आपको अपने उत्तर में तानाशाह की समझ का इस्तेमाल करते हुए एक दृष्टिकोण दिया । यहाँ एक दृष्टिकोण है जो आपके कुछ भाग से संबंधित है।

यदि आप शब्दकोश के मूल्यों के साथ कुछ करना चाहते हैं, तो आपको किसी शब्दकोश की आवश्यकता नहीं है:

iteritems(जब से आपने अपने प्रश्न को टैग किया है, मैं उपयोग कर रहा हूं )

results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])

अब परिणाम some_functionशब्दकोश की प्रत्येक कुंजी / मूल्य जोड़ी के साथ एक सूची में होगा , जो fooइसकी कुंजी में है।

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

results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])

some_function कोई भी कॉल करने योग्य हो सकता है, इसलिए एक मेमना भी काम करेगा:

results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])

आंतरिक सूची की वास्तव में आवश्यकता नहीं है, क्योंकि आप एक जनरेटर अभिव्यक्ति को मानचित्र के रूप में अच्छी तरह से पास कर सकते हैं :

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]

दिलचस्प। कुछ_फंक्शन को कैसे परिभाषित किया जाएगा? पहले मामले में (k, v), क्या यह सिर्फ दो पैरामीटर लेता है? पहली कुंजी फिर मूल्य?
मेमो

हां, सिर्फ एक कॉल करने योग्य। तो map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))- यह आपको देगा [4]
बुरहान खालिद

यह सही है, लेकिन उपयोग करने mapकी तुलना में अधिक पायथोनिक एक सूची समझ है। [f(v) for k, v in d.iteritems() if substring in k]मुझे लगता है कि यह बहुत अधिक पठनीय है, और अधिक कुशल है।
डेविड

@ मीमो यह दो पैरामीटर नहीं लेगा, यह दो तत्वों के साथ एक एकल पैरामीटर लेगा। वहाँ भी starmap है जो दो तर्कों में अनपैक करेगा, हालांकि यह एक आलसी इटरेटर है (इसे निष्पादित करने से पहले, इसे पुनरावृत्त किया जाना चाहिए, अर्थात results = list(starmap(...))या for result in starmap(...): ...)।
nmclean
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.