ডিক্ট থেকে খালি স্ট্রিং সহ কীগুলি সরানোর কার্যকর উপায়


116

আমার একটি ডিক আছে এবং আমি খালি মানের স্ট্রিং রয়েছে এমন সমস্ত কী সরিয়ে দিতে চাই।

metadata = {u'Composite:PreviewImage': u'(Binary data 101973 bytes)',
            u'EXIF:CFAPattern2': u''}

এই কাজ করতে সবচেয়ে ভালো উপায় কি?

উত্তর:


194

পাইথন 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}

মনে রাখবেন যে আপনার সমস্ত কীগুলির মান রয়েছে। এটি কেবলমাত্র সেই মানগুলির মধ্যে কিছুটি খালি স্ট্রিং। মান ব্যতীত ডিকের চাবি বলে কোনও জিনিস নেই; যদি এর কোনও মান না থাকে তবে এটি ডিকের মধ্যে থাকবে না।


29
+1 টি। এটি লক্ষণীয় গুরুত্বপূর্ণ যে এটি কোনও বিদ্যমান অভিধান থেকে কীগুলি সরিয়ে দেয় না। বরং এটি একটি নতুন অভিধান তৈরি করে। সাধারণত এটি হ'ল যে কেউ চান এবং সম্ভবত ওপিটির প্রয়োজন হয় তবে এটি ওপি যা চেয়েছিল তা নয়।
স্টিভেন রাম্বালস্কি

18
এটি ভি = 0 কেও মেরে ফেলেছে, যা ঠিক আছে, যদি এটি চেয়েছিল।
পল

2
এটি v = মিথ্যা থেকেও রক্ষা পায়, যা ওপি যা বলেছিল তা ঠিক নয় ।
আমির

4
@shredding: আপনি বলতে চাচ্ছেন .items()
ব্রেণবার্ন

6
পাইথনের পরবর্তী সংস্করণগুলির জন্য আপনার অভিধান জেনারেটরটিও ব্যবহার করা উচিত:{k: v for k, v in metadata.items() if v is not None}
শিয়াভিণী

75

এটি ব্রেনবারনের সমাধানের চেয়ে আরও ছোট হতে পারে (এবং আমি মনে করি আরও পাঠযোগ্য)

{k: v for k, v in metadata.items() if v}

পাইথন ২.7.৩ দিয়ে পরীক্ষা করা হয়েছে।


13
এটি শূন্য মানকেও হত্যা করে।
পল

10
0 (শূন্য) সংরক্ষণের জন্য আপনি এর ... if v!=Noneমতো ব্যবহার করতে পারেন : {k: v for k, v in metadata.items() if v!=None}
ড্যানিড

1
{k: v for k, v in metadata.items () if v! = काहीही} খালি স্ট্রিং থেকে মুক্তি পাবে না।
ফিলোগো 20

1
পূর্ববর্তী সংস্করণগুলির সাথে সামঞ্জস্যের জন্য অভিধান বোধগম্যতা কেবল পাইথন ২.7++ সমর্থন করে দয়া করে @ ব্রেইনবার্নের সমাধানটি ব্যবহার করুন।
পবন গুপ্ত 18

12
সর্বদা '! =' এর পরিবর্তে 'নয়,' এর সাথে কারও সাথে তুলনা করা উচিত। stackoverflow.com/a/14247419/2368836
rocktheartsm4l

21

আপনার যদি সত্যিই মূল অভিধানটি পরিবর্তন করতে হয়:

empty_keys = [k for k,v in metadata.iteritems() if not v]
for k in empty_keys:
    del metadata[k]

নোট করুন যে আমাদের খালি কীগুলির একটি তালিকা তৈরি করতে হবে কারণ আমরা এর মাধ্যমে পুনরাবৃত্ত হওয়ার সময় কোনও অভিধান পরিবর্তন করতে পারি না (যেমন আপনি লক্ষ্য করেছেন)। খালি মান সহ প্রচুর এন্ট্রি না থাকলে এটি ব্র্যান্ড-নতুন অভিধান তৈরি করার চেয়ে কম ব্যয়বহুল (স্মৃতি অনুসারে) is


এটি 0 এবং 0
মানটিও

2
আপনি যদি পাইথন 3+ ব্যবহার করেন তবে আপনাকে প্রতিস্থাপন .iteritems()করতে হবে .items(), সর্বশেষ পাইথন সংস্করণে প্রথমটি আর কাজ করে না।
মারিয়ানো রুইজ


12

যদি আপনি বাস্তব-বিশ্বের ডেটা স্ট্রাকচারগুলি প্রায়শ নেস্ট করা এবং এমনকি চক্রও ধারণ করতে পারে তবে পরিচালনা করতে যদি একটি পূর্ণ বৈশিষ্ট্যযুক্ত, তবুও সংক্ষিপ্ত যোগাযোগ চান তবে আমি বল্টন ইউটিলিটি প্যাকেজ থেকে রিম্যাপ ইউটিলিটিটি দেখার পরামর্শ দিই

আপনার প্রকল্পে 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 এবং ৩.৩+ তে পুরোপুরি পরীক্ষিত। শ্রেষ্ঠ সব, আমি ভালো ঠিক ক্ষেত্রে এটা লিখেছে, আপনি একটি মামলা এটি পরিচালনা করে না এটি তাই যদি, আপনি বাগ আমাকে এটা ঠিক করতে পারেন এখানে ডান


1
এই সমাধানটি আমার মতো একই সমস্যার জন্য দুর্দান্ত কাজ করেছে: অভিধানের ভিতরে গভীরভাবে নেস্টেড তালিকা থেকে খালি মানগুলি ছিনিয়ে নেওয়া। ধন্যবাদ!
নিকোলাস তুলাচ

1
এটি ভাল, যেহেতু আপনি চাকাটি পুনরায় উদ্ভাবন করছেন না এবং নীড়যুক্ত জিনিসগুলির জন্য একটি সমাধান সরবরাহ করছেন। ধন্যবাদ!
vekerdyb

1
আপনার গ্রন্থাগারের জন্য আপনি যে নিবন্ধটি লিখেছেন তা আমি সত্যিই পছন্দ করেছি এবং এটি একটি দরকারী লাইব্রেরি!
lifelogger

11

রায়ান এর সমাধানের ভিত্তিতে , যদি আপনার কাছে তালিকা এবং নেস্টেড ডিকশনারি থাকে:

পাইথন 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

1
হা, দুর্দান্ত এক্সটেনশন! এটি নিম্নলিখিতগুলির মতো অভিধানের জন্য একটি ভাল সমাধান:d = { "things": [{ "name": "" }] }
রায়ান শেয়া

6

আপনার যদি নেস্টেড ডিকশনারি থাকে এবং আপনি খালি উপ-উপাদানগুলির জন্য এটি কাজ করতে চান তবে আপনি ব্রেইনবার্নের পরামর্শের পুনরাবৃত্ত রূপটি ব্যবহার করতে পারেন:

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
andydavies

6

দ্রুত উত্তর (টিএল; ডিআর)

Example01

### 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'}
'''

বিস্তারিত উত্তর

সমস্যা

  • প্রসঙ্গ: পাইথন 2.x
  • পরিস্থিতি: বিকাশকারী শূন্য মানগুলি বাদ দিতে একটি অভিধানকে সংশোধন করতে চায়
    • ওরেক একটি অভিধান থেকে খালি মান মুছে ফেলুন
    • ওরফে ফাঁকা মান সহ কী মুছুন
    • প্রতিটি কী-মান জোড়ের তুলনায় অ-ফাঁকা মানগুলির জন্য অরফ ফিল্টার অভিধান

সমাধান

  • উদাহরণস্বরূপ "খালি" মানগুলি সরাতে সরল শর্তসাপেক্ষে পাইথন তালিকা-বোঝার সিনট্যাক্স ব্যবহার করুন

pitfalls

  • উদাহরণ01 কেবলমাত্র মূল অভিধানের একটি অনুলিপিটিতে কাজ করে (জায়গায় পরিবর্তন করে না)
  • উদাহরণস্বরূপ01 "খালি" দ্বারা বিকাশকারী কী বোঝায় তার উপর নির্ভর করে অপ্রত্যাশিত ফলাফল আনতে পারে
    • বিকাশকারী মানে কি মিথ্যা মান রয়েছে ?
    • অভিধানে মানগুলি স্ট্রিং হিসাবে গ্যারান্টেড না হলে বিকাশকারীটির অপ্রত্যাশিত ডেটা হ্রাস হতে পারে।
    • ফলাফল01 দেখায় যে মূল সেট থেকে কেবল তিনটি মূল-মান জুড়ি সংরক্ষণ করা হয়েছিল

বিকল্প উদাহরণ

  • উদাহরণ02 সম্ভাব্য সমস্যাগুলি মোকাবেলায় সহায়তা করে
  • পদ্ধতির শর্তাধীন পরিবর্তন করে "খালি" এর আরও সুনির্দিষ্ট সংজ্ঞা ব্যবহার করা to
  • এখানে আমরা কেবলমাত্র মানগুলি ফিল্টার করতে চাই যা খালি স্ট্রিংগুলিতে মূল্যায়ন করে।
  • এখানে আমরা শুধুমাত্র শ্বেতস্পেসের সমন্বিত মানগুলি ফিল্টার আউট করতে .strip () ব্যবহার করি।

Example02

### 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'
  }
'''

আরো দেখুন



4

প্যাট্রিসিয়স এবং নিউনিওর থেকে উত্তর তৈরি করা এবং আপনি সম্ভবত কিছু নির্দিষ্ট নকল জিনিস (উদাহরণস্বরূপ '') অন্যদের (উদাহরণস্বরূপ 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])}

সত্যিই দুর্দান্ত শট, এটি একবারে অনেক সমস্যার সমাধান করে এবং এটি প্রশ্নটি সমাধান করে, এটি পরিষ্কার করার জন্য আপনাকে ধন্যবাদ
jlandercy

শান্ত! এটি এই উদাহরণের জন্য কাজ করে। যাইহোক, []
অভিধানে

2

আমি এই থ্রেডের সমস্ত জবাবগুলি পড়েছি এবং কিছু এই থ্রেডের সাথেও উল্লেখ করা হয়েছে: পুনরাবৃত্ত ফাংশন সহ নেস্টেড ডিকশনারিতে খালি ডালিগুলি সরান

আমি এখানে মূলত সমাধানটি ব্যবহার করেছি এবং এটি দুর্দান্ত কাজ করেছে:

চেষ্টা 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 বিশ্বে কিছু কার্য সম্পাদন এবং সামঞ্জস্যতা উদ্বেগ উত্থাপিত হয়েছিল:

  1. isinstanceপরিবর্তে ব্যবহার করুনtype
  2. forদক্ষতার জন্য লুপে তালিকাটি কম্পলিকে আনরোল করুন
  3. এর 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

1
আমি অন্ধ না হলে এটি আমার কাছে মনে হয় 2 এবং 3
চেষ্টাটি

1

অ্যারেগুলির সাথে মিশ্রিত ডিক্টস

  • 3 চেষ্টা করে উত্তর : ব্লিসরেজের উত্তর থেকে ঠিক ডান (এতদূর) অ্যারে উপাদানগুলি সঠিকভাবে পরিচালনা করে না। কারওর প্রয়োজন হলে আমি একটি প্যাচ অন্তর্ভুক্ত করছি। পদ্ধতিটি হ'ল স্ট্যান্ডমেন্টের স্টেটমেন্ট ব্লকের সাথে 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

অসাধারণ . । । আমি কোড বেসে এই পরিবর্তনটি করেছি তবে আপনার মন্তব্য _ / _
করলাম

0

একটি বিকল্প উপায় আপনি এটি করতে পারেন, অভিধান বোধগম্যতা ব্যবহার করে। এটি সঙ্গে সামঞ্জস্য করা উচিত2.7+

result = {
    key: value for key, value in
    {"foo": "bar", "lorem": None}.items()
    if value
}

0

আপনি যদি ব্যবহার করছেন তবে এখানে একটি বিকল্প রয়েছে 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.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

0

"আমি যেমন পাইথনের সাথে আমার কাজের জন্য একটি ডেস্কটপ অ্যাপ্লিকেশন লিখি তখন প্রচুর এন্ট্রি থাকাকালীন এবং ডেটা-এন্ট্রি অ্যাপ্লিকেশনটিতে আমি পেয়েছি এবং যা কিছু বাধ্যতামূলক নয় তাই ব্যবহারকারীর এটিকে ফাঁকা রেখে দিতে পারে, বৈধতার উদ্দেশ্যে, এটি দখল করা সহজ 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'}

দয়া করে অজগর সংস্করণ উল্লেখ করুন এটি সর্বশেষ সংস্করণকে সমর্থন করবে?
হাসিব মীর

আপনার উত্তরটি বর্তমানে নিম্নমানের মোছা হতে পারে বলে পতাকাঙ্কিত করা হয়েছে। আপনার উত্তরটি যে কোনও কোড বাদ রেখে নিশ্চিত করেছে তা নিশ্চিত করুন।
টিম স্ট্যাক

@ টিমস্ট্যাক দয়া করে এলকিউ উত্তরগুলির জন্য মুছার প্রস্তাব দিন।
10

@ 10Rep আমি এমন কোনও উত্তরের জন্য মোছার প্রস্তাব দেব না যা সমাধান হিসাবে কাজ করতে পারে তবে কেবল কোনও বর্ণনামূলক মন্তব্য নেই is আমি বরং ব্যবহারকারীকে অবহিত করব এবং আরও ভাল উত্তর কেমন দেখাচ্ছে তা তাদের শিখিয়ে দেব।
টিম স্ট্যাক

@ হাসবেব মীর আমি সর্বশেষ পাইথন ৩.৮.৩ ব্যবহার করি
কোকোএফ্রাইম

-2

কিছু মানদণ্ড:

1. তালিকা বোধগম্যতা পুনর্গঠন ডিক

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

3. লুপ এবং মুছুন কী যদি ভি না হয়

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 এ নিয়ে আসে। এছাড়াও আমার কাছে পাইপাই নীট অজগর থেকে প্রায় দ্বিগুণ দ্রুত ছিল।


লুপ এবং মুছে ফেলাও রানটাইমআরার নিক্ষেপ করতে পারে, যেহেতু একটি ভিউ পুনরাবৃত্তি করার সময় কোনও অভিধানকে সংশোধন করা বৈধ নয়। docs.python.org/3/library/stdtyype.html s4.10.1
লিমিটেড

আহ ম্যান হ্যাঁ ঠিক আছে অজগর 3 এ সত্য তবে পাইথন ২.7 এ নয় যেমন আইটেমগুলি একটি তালিকা ফেরত দেয়, তাই আপনাকে list(dic.items())পাইতে কল করতে হবে D. তখন ডিক্ট বোধগম্যতা কি এফটিডব্লিউ? নাল / খালি মানগুলির কম অনুপাতের জন্য ডেল এখনও দ্রুত বলে মনে হচ্ছে। আমি অনুমান করি যে তালিকাটি তৈরি করা কেবল ডিকটি পুনরায় তৈরি করার চেয়ে মেমরির ব্যবহারের পক্ষে ঠিক খারাপ।
রিচার্ড ম্যাথি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.