답변:
파이썬 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}
모든 키에는 값이 있습니다. 그 값 중 일부는 빈 문자열입니다. 딕셔너리에 값이없는 키 같은 것은 없습니다. 값이 없다면 dict에 없을 것입니다.
.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}
Python 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()
합니다. 첫 번째는 최신 Python 버전에서 더 이상 작동하지 않습니다.
BrenBarn의 솔루션 은 이상적입니다 (그리고 pythonic, 추가 할 수도 있습니다). 그러나 다음은 또 다른 (fp) 솔루션입니다.
from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))
자주 중첩되고 주기도 포함 할 수있는 실제 데이터 구조를 처리하는 데 완전한 기능을 제공하면서도 간결한 접근 방식을 원한다면 boltons 유틸리티 패키지에서 remap 유틸리티를 살펴 보는 것이 좋습니다 .
iterutils.py 를 프로젝트에 pip 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 이상에서 완전히 테스트되었습니다. 무엇보다 정확히 이와 같은 경우에 대해 작성 했으므로 처리되지 않는 경우를 발견하면 여기에서 바로 수정하도록 저를 괴롭힐 수 있습니다 .
를 기반으로 라이언의 솔루션 , 당신은 또한 목록 및 중첩 된 사전이있는 경우 :
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
d = { "things": [{ "name": "" }] }
중첩 된 사전이 있고 빈 하위 요소에 대해서도 작동하도록하려면 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
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'
}
'''
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
그러나 Python 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 : Just Right (지금까지) :
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
다음을 사용하는 경우 옵션이 있습니다 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
"현재 Python 작업을위한 데스크톱 응용 프로그램을 작성하고 있기 때문에 데이터 입력 응용 프로그램에서 많은 항목이 있고 일부는 필수 사항이 아니므로 사용자가 유효성 검사를 위해 비워 둘 수 있습니다. 모든 항목을 입력 한 다음 사전의 빈 키 또는 값을 버립니다. 그래서 위의 코드는 사전 이해를 사용하여 쉽게 꺼내고 공백이 아닌 사전 값 요소를 유지하는 방법을 보여줍니다. 나는 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'}
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는 neet python보다 약 두 배 빠릅니다.
list(dic.items())
py 3 을 호출해야하므로 Dict comprehension ftw? del은 Null / 빈 값의 낮은 비율에 대해 여전히 더 빠릅니다. 나는 그 목록을 작성하는 것이 단지 dict를 다시 만드는 것보다 메모리 소비에 좋지 않다고 생각합니다.