programing

사전에서 여러 키를 안전하게 제거

muds 2023. 6. 30. 22:39
반응형

사전에서 여러 키를 안전하게 제거

항목을 제거하는 방법을 알고 있습니다.'key'내 사전에서.d안전하게사용자:

if d.has_key('key'):
    del d['key']

그러나 사전에서 여러 항목을 안전하게 제거해야 합니다.이 작업을 두 번 이상 수행해야 하기 때문에 항목을 튜플로 정의하려고 합니다.

entities_to_remove = ('a', 'b', 'c')
for x in entities_to_remove:
    if x in d:
        del d[x]

하지만, 저는 이것을 하는 더 똑똑한 방법이 있는지 궁금합니다.

사용:

d = {'some': 'data'}
entries_to_remove = ('any', 'iterable')
for k in entries_to_remove:
    d.pop(k, None)

딕트 이해 사용

final_dict = {key: value for key, value in d if key not in [key1, key2]}

여기서 key1key2를 제거합니다.

아래 예제에서는 키 "b"와 "c"를 제거하고 키 목록에 유지합니다.

>>> a
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>> keys = ["b", "c"]
>>> print {key: a[key] for key in a if key not in keys}
{'a': 1, 'd': 4}
>>> 

이렇게 하는 게 어때요?

entries = ('a', 'b', 'c')
the_dict = {'b': 'foo'}

def entries_to_remove(entries, the_dict):
    for key in entries:
        if key in the_dict:
            del the_dict[key]

mattbornski는 dict.pop()을 사용하여 보다 컴팩트한 버전을 제공했습니다.

해결책이 사용되고 있습니다.map그리고.filter

파이썬 2

d={"a":1,"b":2,"c":3}
l=("a","b","d")
map(d.__delitem__, filter(d.__contains__,l))
print(d)

파이썬 3

d={"a":1,"b":2,"c":3}
l=("a","b","d")
list(map(d.__delitem__, filter(d.__contains__,l)))
print(d)

다음과 같은 정보를 얻을 수 있는 것:

{'c': 3}

제거할 키의 값도 검색해야 하는 경우 이 방법을 사용하는 것이 좋습니다.

values_removed = [d.pop(k, None) for k in entities_to_remove]

물론 키를 제거하는 것만으로도 이 작업을 수행할 수 있습니다.d하지만 당신은 목록 이해력이 있는 값 목록을 불필요하게 만들 것입니다.함수의 부작용만을 위해 목록 이해를 사용하는 것도 약간 불분명합니다.

다음을 통해 솔루션을 찾았습니다.pop그리고.map

d = {'a': 'valueA', 'b': 'valueB', 'c': 'valueC', 'd': 'valueD'}
keys = ['a', 'b', 'c']
list(map(d.pop, keys))
print(d)

이 결과는 다음과 같습니다.

{'d': 'valueD'}

이 질문에 답을 늦게 한 이유는 누구나 같은 검색을 하면 앞으로 도움이 될 것 같아서입니다.그리고 이것은 도움이 될 수 있습니다.

갱신하다

위의 코드는 딕트에 키가 존재하지 않으면 오류를 발생시킵니다.

DICTIONARY = {'a': 'valueA', 'b': 'valueB', 'c': 'valueC', 'd': 'valueD'}
keys = ['a', 'l', 'c']

def remove_key(key):
    DICTIONARY.pop(key, None)
    

list(map(remove_key, keys))
print(DICTIONARY)

출력:

DICTIONARY = {'b': 'valueB', 'd': 'valueD'}

cpython 3에 대한 일부 타이밍 테스트는 루프를 위한 간단한 방법이 가장 빠른 방법임을 보여주며, 꽤 읽기 쉽습니다.함수를 추가해도 오버헤드가 크지 않습니다.

결과 시간(10k 반복):

  • all(x.pop(v) for v in r) # 0.85
  • all(map(x.pop, r)) # 0.60
  • list(map(x.pop, r)) # 0.70
  • all(map(x.__delitem__, r)) # 0.44
  • del_all(x, r) # 0.40
  • <inline for loop>(x, r) # 0.35
def del_all(mapping, to_remove):
      """Remove list of elements from mapping."""
      for key in to_remove:
          del mapping[key]

작은 반복의 경우 함수 호출의 오버헤드 때문에 '인라인'을 수행하는 것이 조금 더 빠릅니다.그렇지만del_all는 보풀 안전하고 재사용 가능하며 모든 파이썬 이해 및 매핑 구성보다 빠릅니다.

기존 답변에는 문제가 없지만, 이 솔루션을 찾지 못해 놀랐습니다.

keys_to_remove = ['a', 'b', 'c']
my_dict = {k: v for k, v in zip("a b c d e f g".split(' '), [0, 1, 2, 3, 4, 5, 6])}

for k in keys_to_remove:
    try:
        del my_dict[k]
    except KeyError:
        pass

assert my_dict == {'d': 3, 'e': 4, 'f': 5, 'g': 6}

참고: 저는 여기서 우연히 이 질문을 발견했습니다.그리고 제 대답은 이 대답과 관련이 있습니다.

세 가지 방법의 성능을 테스트했습니다.

# Method 1: `del`
for key in remove_keys:
    if key in d:
        del d[key]

# Method 2: `pop()`
for key in remove_keys:
    d.pop(key, None)

# Method 3: comprehension
{key: v for key, v in d.items() if key not in remove_keys}

다음은 1M 반복의 결과입니다.

  1. del 2 2.03s 2.0ns/리터(100%)
  2. pop() 2 ( 2.38s 2.4ns/iter (117%)
  3. 이해력: 4.11s 4.1ns/iter (202%)

그래서 둘 다del그리고.pop()가장 빠릅니다.이해 속도가 2배 느립니다.하지만 어쨌든, 우리는 여기서 나노초를 말합니다 :) 파이썬의 딕트는 터무니없이 빠릅니다.

그렇지 않은 이유:

entriestoremove = (2,5,1)
for e in entriestoremove:
    if d.has_key(e):
        del d[e]

"똑똑한 방법"이 무슨 뜻인지 모르겠습니다.물론 사전적 이해를 통해 다른 방법이 있을 수 있습니다.

entriestoremove = (2,5,1)
newdict = {x for x in d if x not in entriestoremove}

인라인의

import functools

#: not key(c) in d
d = {"a": "avalue", "b": "bvalue", "d": "dvalue"}

entitiesToREmove = ('a', 'b', 'c')

#: python2
map(lambda x: functools.partial(d.pop, x, None)(), entitiesToREmove)

#: python3

list(map(lambda x: functools.partial(d.pop, x, None)(), entitiesToREmove))

print(d)
# output: {'d': 'dvalue'}

키를 세트로 취급할 수 있다는 사실을 사용하는 것이 파이썬 3에 있다면 가장 좋은 방법이라고 생각합니다.

def remove_keys(d, keys):
    to_remove = set(keys)
    filtered_keys = d.keys() - to_remove
    filtered_values = map(d.get, filtered_keys)
    return dict(zip(filtered_keys, filtered_values))

예:

>>> remove_keys({'k1': 1, 'k3': 3}, ['k1', 'k2'])
{'k3': 3}

키 집합을 "제거"할 수 있도록 사전 세트 메소드(Python 3.9에서 발생하는 끔찍한 혼란이 아니라)를 완전히 지원하는 것이 좋습니다.그러나 제거할 키가 많은 대형 사전이 있는 경우에는 성능에 대해 알고 싶을 수도 있습니다.그래서, 저는 의미 있는 비교를 할 수 있을 만큼 충분히 큰 것을 만드는 코드를 만들었습니다. 100,000 x 1000 행렬, 그러니까 총 10,000,00개 항목입니다.

from itertools import product
from time import perf_counter

# make a complete worksheet 100000 * 1000
start = perf_counter()
prod = product(range(1, 100000), range(1, 1000))
cells = {(x,y):x for x,y in prod}
print(len(cells))

print(f"Create time {perf_counter()-start:.2f}s")
clock = perf_counter()
# remove everything above row 50,000

keys = product(range(50000, 100000), range(1, 100))

# for x,y in keys:
#     del cells[x, y]

for n in map(cells.pop, keys):
    pass

print(len(cells))
stop = perf_counter()
print(f"Removal time {stop-clock:.2f}s")

1,000만 개 이상의 항목은 일부 설정에서 일반적이지 않습니다.로컬 컴퓨터에서 두 가지 방법을 비교해 보면 사용 시 약간의 개선이 있음을 알 수 있습니다.map그리고.pop아마도 함수 호출 수가 적기 때문이겠지만, 둘 다 내 기계에서 약 2.5초를 사용합니다.그러나 이는 사전을 만드는 데 필요한 시간(55초)이나 루프 내의 검사를 포함하는 데 필요한 시간에 비해 부족합니다.이 경우 사전 키와 필터가 교차하는 집합을 만드는 것이 가장 좋습니다.

keys = cells.keys() & keys

요약:del이미 매우 최적화되어 있으므로 사용에 대해 걱정할 필요가 없습니다.

사전에서 키 목록을 제거하는 다른 맵() 방법

KeyError 예외를 발생시키지 마십시오.

    dic = {
        'key1': 1,
        'key2': 2,
        'key3': 3,
        'key4': 4,
        'key5': 5,
    }
    
keys_to_remove = ['key_not_exist', 'key1', 'key2', 'key3']
k = list(map(dic.pop, keys_to_remove, keys_to_remove))

print('k=', k)
print('dic after =  \n', dic)

**this will produce output** 

k= ['key_not_exist', 1, 2, 3]
dic after =  {'key4': 4, 'key5': 5}

중복keys_to_remove인위적이므로 dict.pop() 함수에 대한 기본값을 제공해야 합니다.len_ = len(key_to_remove)으로 배열을 추가할 수 있습니다.


예를들면

dic = {
    'key1': 1,
    'key2': 2,
    'key3': 3,
    'key4': 4,
    'key5': 5,
}

keys_to_remove = ['key_not_exist', 'key1', 'key2', 'key3']    
k = list(map(dic.pop, keys_to_remove, np.zeros(len(keys_to_remove))))

print('k=', k)
print('dic after = ', dic)

출력 **을 생성합니다.

k= [0.0, 1, 2, 3]
dic after =  {'key4': 4, 'key5': 5}
def delete_keys_from_dict(dictionary, keys):
"""
Deletes the unwanted keys in the dictionary
:param dictionary: dict
:param keys: list of keys
:return: dict (modified)
"""
from collections.abc import MutableMapping

keys_set = set(keys)
modified_dict = {}
for key, value in dictionary.items():
    if key not in keys_set:
        if isinstance(value, list):
            modified_dict[key] = list()
            for x in value:
                if isinstance(x, MutableMapping):
                    modified_dict[key].append(delete_keys_from_dict(x, keys_set))
                else:
                    modified_dict[key].append(x)
        elif isinstance(value, MutableMapping):
            modified_dict[key] = delete_keys_from_dict(value, keys_set)
        else:
            modified_dict[key] = value
return modified_dict


_d = {'a': 1245, 'b': 1234325, 'c': {'a': 1245, 'b': 1234325}, 'd': 98765,
      'e': [{'a': 1245, 'b': 1234325},
            {'a': 1245, 'b': 1234325},
            {'t': 767}]}

_output = delete_keys_from_dict(_d, ['a', 'b'])
_expected = {'c': {}, 'd': 98765, 'e': [{}, {}, {'t': 767}]}
print(_expected)
print(_output)

다른 사람 말고는 이 토론에 늦었습니다.이러한 키 목록을 만드는 것이 해결책일 수 있습니다.

k = ['a','b','c','d']

그런 다음 목록 이해에서 pop()을 사용하거나 루프에 대해 pop()을 사용하여 키 위에서 반복하고 한 번에 하나씩 팝합니다.

new_dictionary = [dictionary.pop(x, 'n/a') for x in k]

'n/a'는 키가 존재하지 않는 경우 기본값을 반환해야 합니다.

언급URL : https://stackoverflow.com/questions/8995611/removing-multiple-keys-from-a-dictionary-safely

반응형