137

dict があり、空の値の文字列があるすべてのキーを削除したいと考えています。

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

これを行う最善の方法は何ですか?

4

19 に答える 19

227

Python 2.X

dict((k, v) for k, v in metadata.iteritems() if v)

Python 2.7 - 3.X

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

すべてのキーに値があることに注意してください。これらの値の一部が空の文字列であることだけです。値のない dict にはキーのようなものはありません。値がない場合は、dict に含まれません。

于 2012-08-25T02:36:42.863 に答える
22

元の辞書を本当に変更する必要がある場合:

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

空のキーのリストを作成する必要があることに注意してください。これは、反復処理中に辞書を変更できないためです (お気づきかもしれません)。ただし、空の値を持つエントリが多数ない限り、これは真新しいディクショナリを作成するよりもコストがかかりません (メモリの観点から)。

于 2012-08-25T03:09:03.010 に答える
17

多くの場合ネストされ、サイクルを含むことさえある実世界のデータ構造を処理するためのフル機能でありながら簡潔なアプローチが必要な場合は、boltons ユーティリティ パッケージの remap ユーティリティを参照することをお勧めします。

プロジェクトにiterutils.pypip install boltonsをコピーまたはコピーした後、次のようにします。

from boltons.iterutils import remap

drop_falsey = lambda path, key, value: bool(value)
clean = remap(metadata, visit=drop_falsey)

このページには、Github の API からのはるかに大きなオブジェクトを操作するものなど、さらに多くの例があります。

これは純粋な Python であるため、どこでも機能し、Python 2.7 および 3.3+ で完全にテストされています。何よりも、私はまさにこのようなケースのために書いたので、処理できないケースを見つけた場合は、ここでバグを修正することができます.

于 2016-02-08T05:09:47.353 に答える
15

Ryan's solutionに基づいて、リストとネストされた辞書もある場合:

Python 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

Python 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
于 2014-07-22T16:51:59.367 に答える
13

BrenBarn のソリューションは理想的です (そして pythonic だと付け加えるかもしれません)。ただし、別の(fp)ソリューションを次に示します。

from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))
于 2012-08-25T03:00:14.600 に答える
8

ネストされた辞書があり、空のサブ要素に対してもこれを機能させたい場合は、BrenBarn の提案の再帰的バリアントを使用できます。

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
于 2014-07-11T01:16:45.567 に答える
6

クイックアンサー (TL;DR)

例01

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

詳細な回答

問題

  • コンテキスト: Python 2.x
  • シナリオ:開発者は辞書を変更して空白の値を除外したい
    • 別名、辞書から空の値を削除します
    • 別名、空白の値を持つキーを削除します
    • 各キーと値のペアに対する空白以外の値の別名フィルター辞書

解決

  • example01 単純な条件付きの Python リスト内包表記構文を使用して、「空の」値を削除します

落とし穴

  • example01 は元の辞書のコピーに対してのみ動作します (その場で変更しません)
  • example01 は、開発者が「空」で何を意味するかによって、予期しない結果をもたらす可能性があります
    • 開発者は偽りの値を保持するつもりですか?
    • ディクショナリ内の値が文字列であることが保証されていない場合、開発者は予期しないデータ損失を被る可能性があります。
    • result01 は、元のセットから 3 つのキーと値のペアのみが保持されたことを示しています

代替例

  • example02 は潜在的な落とし穴に対処するのに役立ちます
  • アプローチは、条件を変更して「空」のより正確な定義を使用することです。
  • ここでは、空の文字列に評価される値のみを除外します。
  • ここでも .strip() を使用して、空白のみで構成される値を除外します。

例02

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

こちらもご覧ください

于 2015-10-31T19:29:37.567 に答える
4

patriciasznneonneoからの回答に基づいて構築し、特定の偽物のみを含むキー (例: '') を削除し、他のものを含まないキー (例: 0)、またはいくつかの真実のものを含めたい場合(例: 'SPAM')の可能性を説明します。、次に非常に具体的なヒットリストを作成できます。

unwanted = ['', u'', None, False, [], 'SPAM']

残念ながら、これはうまくいきませ0 in unwantedTrue0と他の偽物を区別する必要があるため、以下を使用する必要があります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])}
于 2015-11-16T14:55:22.447 に答える
1

配列と混合された辞書

  • BlissRage の回答からの試行 3: Just Right (これまでのところ)の回答は、配列要素を適切に処理しません。誰かがそれを必要とする場合に備えて、パッチを含めています。このメソッドは、元の実装を使用してリストをスクラブするのステートメント ブロックを使用してリストを処理します。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
于 2020-01-29T01:53:08.710 に答える
1

"As I also currently write a desktop application for my work with Python, I found in data-entry application when there is lots of entry and which some are not mandatory thus user can left it blank, for validation purpose, it is easy to grab all entries and then discard empty key or value of a dictionary. So my code above a show how we can easy take them out, using dictionary comprehension and keep dictionary value element which is not blank. I use Python 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'}
于 2020-07-22T10:04:25.897 に答える
0
metadata ={'src':'1921','dest':'1337','email':'','movile':''}
ot = {k: v for k, v in metadata.items() if v != ''}
print(f"Final {ot}")
于 2021-04-23T23:27:34.730 に答える