Mam taki, dict
który ma całą masę wpisów. Interesuje mnie tylko kilka wybranych. Czy istnieje prosty sposób na przycięcie wszystkich pozostałych?
Mam taki, dict
który ma całą masę wpisów. Interesuje mnie tylko kilka wybranych. Czy istnieje prosty sposób na przycięcie wszystkich pozostałych?
Odpowiedzi:
Konstruowanie nowego dykta:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Korzysta ze słownika.
Jeśli używasz wersji, która ich nie ma (tj. Python 2.6 i wcześniejsze), zrób to dict((your_key, old_dict[your_key]) for ...)
. To jest to samo, choć brzydsze.
Zauważ, że w przeciwieństwie do wersji jnnnnn, ma stabilną wydajność (zależy tylko od liczby twoich_kluczy) dla old_dict
s dowolnego rozmiaru. Zarówno pod względem szybkości, jak i pamięci. Ponieważ jest to wyrażenie generatora, przetwarza jeden element na raz i nie przegląda wszystkich elementów old_dict.
Usuwanie wszystkiego na miejscu:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
old_dict
wskazuje na błąd w innym miejscu, i w takim przypadku zdecydowanie wolę błąd niż cicho błędne wyniki.
Nieco bardziej eleganckie rozumienie nagrań:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
mydict.iteritems()
zamiast tego. .items()
tworzy kolejną listę.
Oto przykład w Pythonie 2.6:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
Część filtrująca to if
instrukcja.
Ta metoda jest wolniejsza niż odpowiedź delnana, jeśli chcesz wybrać tylko kilka bardzo wielu kluczy.
if key in ('x','y','z')
.
Możesz to zrobić za pomocą funkcji projektu z mojej biblioteki funcy :
from funcy import project
small_dict = project(big_dict, keys)
Zobacz także select_keys .
Kod 1:
dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
if key % 2 == 0:
d1[key] = value
Kod 2:
dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}
Kod 3:
dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}
Wszystkie składowe wydajności kodu są mierzone za pomocą timeit przy użyciu liczby = 1000 i gromadzone 1000 razy dla każdego fragmentu kodu.
W Pythonie 3.6 wydajność trzech sposobów filtrowania kluczy dyktowania jest prawie taka sama. Dla Pythona 2.7 kod 3 jest nieco szybszy.
Ta liner lambda powinna działać:
dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
Oto przykład:
my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")
# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}
Jest to podstawowe rozumienie listy, iterujące po klawiszach dict (i in x) i wyświetla listę par krotek (klucz, wartość), jeśli klucz znajduje się na żądanej liście kluczy (y). Dict () otacza całość, by wyprowadzić ją jako obiekt dict.
set
do wanted_keys
, ale poza tym wygląda dobrze.
dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))
:, zwraca {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}
zgodnie z przeznaczeniem.
dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}
i wynik był taki {}
, że zakładałem, że jest to puste zdanie.
foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))
:, dostanę: {'0': [1, 3], '2': [1, 4]}
co jest zamierzonym rezultatem
Biorąc pod uwagę oryginalny słownik orig
i zestaw pozycji, którymi jesteś zainteresowany keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
co nie jest tak miłe jak odpowiedź Delnana, ale powinno działać w każdej interesującej wersji Pythona. Jest jednak delikatny dla każdego elementu keys
istniejącego w oryginalnym słowniku.
Na podstawie zaakceptowanej odpowiedzi delnan.
Co zrobić, jeśli jednego z twoich poszukiwanych kluczy nie ma w old_dict? Rozwiązanie Delnan zgłosi wyjątek KeyError, który można przechwycić. Jeśli nie tego potrzebujesz, może chcesz:
uwzględniaj tylko klucze, które istnieją zarówno w old_dict, jak i w zestawie „Want_Key”.
old_dict = {'name':"Foobar", 'baz':42}
wanted_keys = ['name', 'age']
new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
>>> new_dict
{'name': 'Foobar'}
mają wartość domyślną dla kluczy, która nie jest ustawiona w old_dict.
default = None
new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
>>> new_dict
{'age': None, 'name': 'Foobar'}
{k: old_dict.get(k, default) for k in ...}
Ta funkcja załatwi sprawę:
def include_keys(dictionary, keys):
"""Filters a dict by only including certain keys."""
key_set = set(keys) & set(dictionary.keys())
return {key: dictionary[key] for key in key_set}
Podobnie jak wersja delnan, ta wykorzystuje rozumienie słownika i ma stabilną wydajność dla dużych słowników (zależnie tylko od liczby dozwolonych kluczy, a nie od całkowitej liczby kluczy w słowniku).
I podobnie jak wersja MyGGan, ta pozwala na dołączenie do listy kluczy kluczy, które mogą nie istnieć w słowniku.
Jako bonus, oto odwrotność, w której można utworzyć słownik, wykluczając niektóre klucze w oryginale:
def exclude_keys(dictionary, keys):
"""Filters a dict by excluding certain keys."""
key_set = set(dictionary.keys()) - set(keys)
return {key: dictionary[key] for key in key_set}
Zauważ, że w przeciwieństwie do wersji delnana, operacja nie jest wykonywana na miejscu, więc wydajność zależy od liczby kluczy w słowniku. Zaletą tego jest jednak to, że funkcja nie modyfikuje podanego słownika.
Edycja: Dodano osobną funkcję wykluczania niektórych kluczy ze słownika.
invert
oznacza, że keys
argument jest podtrzymywany, czy keys
argument jest odrzucany?”, Ilu z nich się zgodzi?
Jeśli chcemy stworzyć nowy słownik z usuniętymi wybranymi kluczami, możemy skorzystać ze słownika
Na przykład:
d = {
'a' : 1,
'b' : 2,
'c' : 3
}
x = {key:d[key] for key in d.keys() - {'c', 'e'}} # Python 3
y = {key:d[key] for key in set(d.keys()) - {'c', 'e'}} # Python 2.*
# x is {'a': 1, 'b': 2}
# y is {'a': 1, 'b': 2}
Inna opcja:
content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())
Ale otrzymujesz list
(Python 2) lub iterator (Python 3) filter()
, a nie dict
.
filtered
w dict
i wrócisz do słownika!
Oto kolejna prosta metoda wykorzystująca del
w jednym wkładce:
for key in e_keys: del your_dict[key]
e_keys
to lista kluczy do wykluczenia. Zaktualizuje twój dykt, a nie da ci nowy.
Jeśli chcesz nowego nagrania wyjściowego, wykonaj jego kopię przed usunięciem:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
Możesz użyć python-benedict
, to podklasa dict.
Instalacja: pip install python-benedict
from benedict import benedict
dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])
Jest open-source na GitHub: https://github.com/fabiocaccamo/python-benedict
Oświadczenie: Jestem autorem tej biblioteki.