আমার একটি ডিক আছে এবং আমি খালি মানের স্ট্রিং রয়েছে এমন সমস্ত কী সরিয়ে দিতে চাই।
metadata = {u'Composite:PreviewImage': u'(Binary data 101973 bytes)',
u'EXIF:CFAPattern2': u''}
এই কাজ করতে সবচেয়ে ভালো উপায় কি?
আমার একটি ডিক আছে এবং আমি খালি মানের স্ট্রিং রয়েছে এমন সমস্ত কী সরিয়ে দিতে চাই।
metadata = {u'Composite:PreviewImage': u'(Binary data 101973 bytes)',
u'EXIF:CFAPattern2': u''}
এই কাজ করতে সবচেয়ে ভালো উপায় কি?
উত্তর:
পাইথন 2.X
dict((k, v) for k, v in metadata.iteritems() if v)
পাইথন 2.7 - 3. এক্স
{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}
এটি ব্রেনবারনের সমাধানের চেয়ে আরও ছোট হতে পারে (এবং আমি মনে করি আরও পাঠযোগ্য)
{k: v for k, v in metadata.items() if v}
পাইথন ২.7.৩ দিয়ে পরীক্ষা করা হয়েছে।
... 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]
নোট করুন যে আমাদের খালি কীগুলির একটি তালিকা তৈরি করতে হবে কারণ আমরা এর মাধ্যমে পুনরাবৃত্ত হওয়ার সময় কোনও অভিধান পরিবর্তন করতে পারি না (যেমন আপনি লক্ষ্য করেছেন)। খালি মান সহ প্রচুর এন্ট্রি না থাকলে এটি ব্র্যান্ড-নতুন অভিধান তৈরি করার চেয়ে কম ব্যয়বহুল (স্মৃতি অনুসারে) is
.iteritems()
করতে হবে .items()
, সর্বশেষ পাইথন সংস্করণে প্রথমটি আর কাজ করে না।
ব্রেনবারনের সমাধানটি আদর্শ (এবং পাইথোনিক, আমি যুক্ত করতে পারি)। তবে এখানে আরও একটি সমাধান রয়েছে:
from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))
যদি আপনি বাস্তব-বিশ্বের ডেটা স্ট্রাকচারগুলি প্রায়শ নেস্ট করা এবং এমনকি চক্রও ধারণ করতে পারে তবে পরিচালনা করতে যদি একটি পূর্ণ বৈশিষ্ট্যযুক্ত, তবুও সংক্ষিপ্ত যোগাযোগ চান তবে আমি বল্টন ইউটিলিটি প্যাকেজ থেকে রিম্যাপ ইউটিলিটিটি দেখার পরামর্শ দিই ।
আপনার প্রকল্পে iterutils.pypip install boltons
অনুলিপি করার পরে বা অনুলিপি করুন , কেবল করুন:
from boltons.iterutils import remap
drop_falsey = lambda path, key, value: bool(value)
clean = remap(metadata, visit=drop_falsey)
এই পৃষ্ঠায় আরও অনেক উদাহরণ রয়েছে, গিথুব এর এপিআই থেকে অনেক বড় অবজেক্টের সাথে কাজ করা সহ including
এটি খাঁটি-পাইথন, সুতরাং এটি সর্বত্র কাজ করে এবং পাইথন ২.7 এবং ৩.৩+ তে পুরোপুরি পরীক্ষিত। শ্রেষ্ঠ সব, আমি ভালো ঠিক ক্ষেত্রে এটা লিখেছে, আপনি একটি মামলা এটি পরিচালনা করে না এটি তাই যদি, আপনি বাগ আমাকে এটা ঠিক করতে পারেন এখানে ডান ।
রায়ান এর সমাধানের ভিত্তিতে , যদি আপনার কাছে তালিকা এবং নেস্টেড ডিকশনারি থাকে:
পাইথন 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)
প্যাট্রিসিয়স এবং নিউনিওর থেকে উত্তর তৈরি করা এবং আপনি সম্ভবত কিছু নির্দিষ্ট নকল জিনিস (উদাহরণস্বরূপ ''
) অন্যদের (উদাহরণস্বরূপ 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])}
[]
আমি এই থ্রেডের সমস্ত জবাবগুলি পড়েছি এবং কিছু এই থ্রেডের সাথেও উল্লেখ করা হয়েছে: পুনরাবৃত্ত ফাংশন সহ নেস্টেড ডিকশনারিতে খালি ডালিগুলি সরান
আমি এখানে মূলত সমাধানটি ব্যবহার করেছি এবং এটি দুর্দান্ত কাজ করেছে:
চেষ্টা 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
তবে পাইথন ২.7 বিশ্বে কিছু কার্য সম্পাদন এবং সামঞ্জস্যতা উদ্বেগ উত্থাপিত হয়েছিল:
isinstance
পরিবর্তে ব্যবহার করুনtype
for
দক্ষতার জন্য লুপে তালিকাটি কম্পলিকে আনরোল করুনitems
পরিবর্তে পাইথন 3 নিরাপদ ব্যবহার করুন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
"আমি যেমন পাইথনের সাথে আমার কাজের জন্য একটি ডেস্কটপ অ্যাপ্লিকেশন লিখি তখন প্রচুর এন্ট্রি থাকাকালীন এবং ডেটা-এন্ট্রি অ্যাপ্লিকেশনটিতে আমি পেয়েছি এবং যা কিছু বাধ্যতামূলক নয় তাই ব্যবহারকারীর এটিকে ফাঁকা রেখে দিতে পারে, বৈধতার উদ্দেশ্যে, এটি দখল করা সহজ is সমস্ত এন্ট্রি এবং তারপরে একটি অভিধানের খালি কী বা মান বাতিল করুন So সুতরাং অভিধানের বোধগম্যতা ব্যবহার করে কীভাবে আমরা সহজেই এগুলি তাদের বাইরে নিয়ে যেতে পারি এবং অভিধানের মান উপাদানটি ফাঁকা নয়, তা রাখতে পারি তার উপরে আমার কোডগুলি। আমি পাইথন ৩.৮.৩ ব্যবহার করি I
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()
আবার আস্তে আবার half 680ns।
একটি কার্যক্রমে 3 মোড়ানো এটিকে আবার প্রায় 275ns এ নিয়ে আসে। এছাড়াও আমার কাছে পাইপাই নীট অজগর থেকে প্রায় দ্বিগুণ দ্রুত ছিল।
list(dic.items())
পাইতে কল করতে হবে D. তখন ডিক্ট বোধগম্যতা কি এফটিডব্লিউ? নাল / খালি মানগুলির কম অনুপাতের জন্য ডেল এখনও দ্রুত বলে মনে হচ্ছে। আমি অনুমান করি যে তালিকাটি তৈরি করা কেবল ডিকটি পুনরায় তৈরি করার চেয়ে মেমরির ব্যবহারের পক্ষে ঠিক খারাপ।