जवाबों:
अजगर 2.X
dict((k, v) for k, v in metadata.iteritems() if v)
पायथन 2.7 - 3.X
{k: v for k, v in metadata.items() if v is not None}
ध्यान दें कि आपकी सभी कुंजियों में मान हैं। यह सिर्फ इतना है कि उन मूल्यों में से कुछ खाली स्ट्रिंग हैं। मूल्य के बिना एक तानाशाह में एक कुंजी के रूप में ऐसी कोई चीज नहीं है; यदि इसका कोई मूल्य नहीं है, तो यह तानाशाही में नहीं होगा।
.items()
।
{k: v for k, v in metadata.items() if v is not None}
यह BrenBarn के समाधान से भी छोटा हो सकता है (और अधिक पठनीय मुझे लगता है)
{k: v for k, v in metadata.items() if v}
पायथन 2.7.3 के साथ परीक्षण किया गया।
... if v!=None
: {k: v for k, v in metadata.items() if v!=None}
यदि आपको वास्तव में मूल शब्दकोश को संशोधित करने की आवश्यकता है:
empty_keys = [k for k,v in metadata.iteritems() if not v]
for k in empty_keys:
del metadata[k]
ध्यान दें कि हमें खाली कुंजियों की एक सूची बनानी होगी क्योंकि हम इसके माध्यम से पुनरावृति करते समय एक शब्दकोश को संशोधित नहीं कर सकते हैं (जैसा कि आपने देखा होगा)। यह एक नया शब्दकोश बनाने की तुलना में कम महंगा (मेमोरी-वार) है, हालांकि, जब तक कि खाली मानों के साथ बहुत सारी प्रविष्टियां नहीं होती हैं।
.iteritems()
के साथ .items()
, पहले नवीनतम अजगर संस्करणों में अब और काम नहीं करता।
ब्रेनबर्न का समाधान आदर्श है (और पायथोनिक , मैं जोड़ सकता हूं)। यहाँ एक और (fp) समाधान है, हालाँकि:
from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))
यदि आप वास्तविक दुनिया डेटा संरचनाओं को संभालने के लिए एक पूर्ण-विशेषताओं, फिर भी रसीला दृष्टिकोण चाहते हैं जो अक्सर नेस्टेड होते हैं, और यहां तक कि चक्र भी हो सकते हैं, तो मैं बोल्ट उपयोगिता उपयोगिता पैकेज से रीमैप उपयोगिता को देखने की सलाह देता हूं ।
अपने प्रोजेक्ट में iterutils.py को pip install boltons
कॉपी या कॉपी करने के बाद , बस करें:
from boltons.iterutils import remap
drop_falsey = lambda path, key, value: bool(value)
clean = remap(metadata, visit=drop_falsey)
इस पृष्ठ के कई और उदाहरण हैं, जिनमें जीथब के एपीआई से बहुत बड़ी वस्तुओं के साथ काम करना शामिल है।
यह शुद्ध-पायथन है, इसलिए यह हर जगह काम करता है, और पायथन 2.7 और 3.3+ में पूरी तरह से परीक्षण किया गया है। सबसे अच्छी बात, मैंने इसे इस तरह के मामलों के लिए लिखा है, इसलिए यदि आपको ऐसा मामला लगता है जो इसे नहीं संभालता है, तो आप मुझे इसे ठीक करने के लिए बग कर सकते हैं ।
रयान के समाधान के आधार पर , यदि आपके पास सूची और नेस्टेड शब्दकोश भी हैं:
पायथन 2 के लिए:
def remove_empty_from_dict(d):
if type(d) is dict:
return dict((k, remove_empty_from_dict(v)) for k, v in d.iteritems() if v and remove_empty_from_dict(v))
elif type(d) is list:
return [remove_empty_from_dict(v) for v in d if v and remove_empty_from_dict(v)]
else:
return d
पायथन 3 के लिए:
def remove_empty_from_dict(d):
if type(d) is dict:
return dict((k, remove_empty_from_dict(v)) for k, v in d.items() if v and remove_empty_from_dict(v))
elif type(d) is list:
return [remove_empty_from_dict(v) for v in d if v and remove_empty_from_dict(v)]
else:
return d
d = { "things": [{ "name": "" }] }
यदि आपके पास एक नेस्टेड शब्दकोश है, और आप चाहते हैं कि यह खाली उप-तत्वों के लिए भी काम करे, तो आप ब्रेनबर्न के सुझाव के पुनरावर्ती संस्करण का उपयोग कर सकते हैं:
def scrub_dict(d):
if type(d) is dict:
return dict((k, scrub_dict(v)) for k, v in d.iteritems() if v and scrub_dict(v))
else:
return d
items()
इसके बजाय iteritems()
पायथन 3 के लिए उपयोग करें
### example01 -------------------
mydict = { "alpha":0,
"bravo":"0",
"charlie":"three",
"delta":[],
"echo":False,
"foxy":"False",
"golf":"",
"hotel":" ",
}
newdict = dict([(vkey, vdata) for vkey, vdata in mydict.iteritems() if(vdata) ])
print newdict
### result01 -------------------
result01 ='''
{'foxy': 'False', 'charlie': 'three', 'bravo': '0'}
'''
### example02 -------------------
mydict = { "alpha":0,
"bravo":"0",
"charlie":"three",
"delta":[],
"echo":False,
"foxy":"False",
"golf":"",
"hotel":" ",
}
newdict = dict([(vkey, vdata) for vkey, vdata in mydict.iteritems() if(str(vdata).strip()) ])
print newdict
### result02 -------------------
result02 ='''
{'alpha': 0,
'bravo': '0',
'charlie': 'three',
'delta': [],
'echo': False,
'foxy': 'False'
}
'''
अजगर 3 के लिए
dict((k, v) for k, v in metadata.items() if v)
Patriciasz और nneonneo से उत्तर पर निर्माण , और इस संभावना के लिए लेखांकन कि आप उन कुंजियों को हटाना चाहते हैं जिनमें केवल कुछ मिथ्या बातें हैं (उदाहरण के लिए ''
) लेकिन अन्य नहीं (उदाहरण के लिए 0
), या शायद आप भी कुछ सत्य चीजें (जैसे 'SPAM'
) शामिल करना चाहते हैं तो आप एक अत्यधिक विशिष्ट हिटलिस्ट बना सकते हैं:
unwanted = ['', u'', None, False, [], 'SPAM']
दुर्भाग्य से, यह काफी काम नहीं करता है, क्योंकि उदाहरण के लिए 0 in unwanted
मूल्यांकन करता है True
। हमें 0
अन्य झूठी चीजों के बीच भेदभाव करने की आवश्यकता है , इसलिए हमें इसका उपयोग करना होगा is
:
any([0 is i for i in unwanted])
... का मूल्यांकन करता है False
।
अब इसका उपयोग del
अवांछित चीजों के लिए करें:
unwanted_keys = [k for k, v in metadata.items() if any([v is i for i in unwanted])]
for k in unwanted_keys: del metadata[k]
यदि आप जगह में संशोधन करने के बजाय एक नया शब्दकोश चाहते हैं metadata
:
newdict = {k: v for k, v in metadata.items() if not any([v is i for i in unwanted])}
[]
मैंने इस धागे में सभी उत्तर पढ़े और कुछ ने इस धागे को भी संदर्भित किया: पुनरावर्ती फ़ंक्शन के साथ नेस्टेड शब्दकोश में खाली dicts निकालें
मैंने मूल रूप से यहां समाधान का इस्तेमाल किया और इसने बहुत अच्छा काम किया:
प्रयास 1: टू हॉट (प्रदर्शन या भविष्य के सबूत नहीं) :
def scrub_dict(d):
if type(d) is dict:
return dict((k, scrub_dict(v)) for k, v in d.iteritems() if v and scrub_dict(v))
else:
return d
लेकिन पायथन 2.7 दुनिया में कुछ प्रदर्शन और संगतता चिंताओं को उठाया गया था:
isinstance
बजाय का उपयोग करेंtype
for
दक्षता के लिए लूप में सूची COMP को अनियंत्रित करेंitems
बजाय सुरक्षित python3 का उपयोग करेंiteritems
प्रयास 2: बहुत ठंडा (यादों की कमी) :
def scrub_dict(d):
new_dict = {}
for k, v in d.items():
if isinstance(v,dict):
v = scrub_dict(v)
if not v in (u'', None, {}):
new_dict[k] = v
return new_dict
DOH! यह पुनरावर्ती नहीं है और संस्मरणात्मक नहीं है।
प्रयास 3: बस सही (अब तक) :
def scrub_dict(d):
new_dict = {}
for k, v in d.items():
if isinstance(v,dict):
v = scrub_dict(v)
if not v in (u'', None, {}):
new_dict[k] = v
return new_dict
if isinstance(v, list):
, जो मूल scrub_dict(d)
कार्यान्वयन का उपयोग करके सूची को स्क्रब करता है। @staticmethod
def scrub_dict(d):
new_dict = {}
for k, v in d.items():
if isinstance(v, dict):
v = scrub_dict(v)
if isinstance(v, list):
v = scrub_list(v)
if not v in (u'', None, {}):
new_dict[k] = v
return new_dict
@staticmethod
def scrub_list(d):
scrubbed_list = []
for i in d:
if isinstance(i, dict):
i = scrub_dict(i)
scrubbed_list.append(i)
return scrubbed_list
एक वैकल्पिक तरीका है कि आप ऐसा कर सकते हैं, शब्दकोश समझ का उपयोग कर रहे हैं। इसके साथ संगत होना चाहिए2.7+
result = {
key: value for key, value in
{"foo": "bar", "lorem": None}.items()
if value
}
यदि आप उपयोग कर रहे हैं तो यहां एक विकल्प है pandas
:
import pandas as pd
d = dict.fromkeys(['a', 'b', 'c', 'd'])
d['b'] = 'not null'
d['c'] = '' # empty string
print(d)
# convert `dict` to `Series` and replace any blank strings with `None`;
# use the `.dropna()` method and
# then convert back to a `dict`
d_ = pd.Series(d).replace('', None).dropna().to_dict()
print(d_)
ऊपर उल्लिखित कुछ विधियाँ उपेक्षा करती हैं यदि कोई पूर्णांक हैं और मान 0 और 0.0 के साथ तैरते हैं
यदि कोई उपरोक्त से बचना चाहता है तो नीचे दिए गए कोड का उपयोग कर सकता है (खाली स्ट्रिंग निकालता है और नेस्टेड डिक्शनरी और नेस्टेड सूची से कोई भी मूल्य नहीं):
def remove_empty_from_dict(d):
if type(d) is dict:
_temp = {}
for k,v in d.items():
if v == None or v == "":
pass
elif type(v) is int or type(v) is float:
_temp[k] = remove_empty_from_dict(v)
elif (v or remove_empty_from_dict(v)):
_temp[k] = remove_empty_from_dict(v)
return _temp
elif type(d) is list:
return [remove_empty_from_dict(v) for v in d if( (str(v).strip() or str(remove_empty_from_dict(v)).strip()) and (v != None or remove_empty_from_dict(v) != None))]
else:
return d
"जैसा कि मैं वर्तमान में पायथन के साथ अपने काम के लिए एक डेस्कटॉप एप्लिकेशन भी लिखता हूं, मैंने डेटा-एंट्री एप्लिकेशन में पाया जब बहुत सारी प्रविष्टि होती है और जो कुछ अनिवार्य नहीं हैं, इस प्रकार उपयोगकर्ता इसे खाली छोड़ सकता है, सत्यापन उद्देश्य के लिए, इसे हथियाना आसान है सभी प्रविष्टियाँ और फिर एक शब्दकोष की खाली कुंजी या मान को छोड़ दें। तो एक शो के ऊपर मेरा कोड, हम कैसे शब्दकोश को आसानी से निकाल सकते हैं, शब्दकोश की समझ का उपयोग करें और शब्दकोश मान तत्व रखें जो रिक्त नहीं है। मैं पायथन 3.8.3 का उपयोग करता हूं।
data = {'':'', '20':'', '50':'', '100':'1.1', '200':'1.2'}
dic = {key:value for key,value in data.items() if value != ''}
print(dic)
{'100': '1.1', '200': '1.2'}
In [7]: %%timeit dic = {str(i):i for i in xrange(10)}; dic['10'] = None; dic['5'] = None
...: dic = {k: v for k, v in dic.items() if v is not None}
1000000 loops, best of 7: 375 ns per loop
In [8]: %%timeit dic = {str(i):i for i in xrange(10)}; dic['10'] = None; dic['5'] = None
...: dic = dict((k, v) for k, v in dic.items() if v is not None)
1000000 loops, best of 7: 681 ns per loop
In [10]: %%timeit dic = {str(i):i for i in xrange(10)}; dic['10'] = None; dic['5'] = None
...: for k, v in dic.items():
...: if v is None:
...: del dic[k]
...:
10000000 loops, best of 7: 160 ns per loop
इसलिए लूप और डिलीट 160ns पर सबसे तेज है, सूची समझ आधी ~ 375ns पर धीमी है और एक कॉल के साथ है dict()
आधा फिर से धीमा है ~ 680ns।
एक समारोह में 3 लपेटकर यह लगभग 275ns को फिर से वापस लाता है। मेरे लिए भी PyPy नीट अजगर से लगभग दोगुना तेज़ था।
list(dic.items())
py में कॉल करना होगा 3. डिक्ट कॉम्प्रिहेंशन ftw तब? डेल अभी भी Null / खाली मानों के कम अनुपात के लिए तेज़ लगता है। मुझे लगता है कि उस सूची का निर्माण स्मृति के उपभोग के लिए सिर्फ उतना ही बुरा है जितना कि तानाशाही को फिर से बनाना।