Python: krotki / słowniki jako klucze, select, sort
Przypuśćmy, że mam ilości owoców o różnych kolorach, np. 24 niebieskie banany, 12 zielonych jabłek, 0 niebieskich truskawek i tak dalej. Chciałbym uporządkować je w strukturze danych w Pythonie, która pozwala na łatwe zaznaczanie i sortowanie. Moim pomysłem było umieszczenie ich w słowniku z krotkami jako kluczami, np.
{ ('banana', 'blue' ): 24,
('apple', 'green'): 12,
('strawberry','blue' ): 0,
...
}
Lub nawet słowniki, np.
{ {'fruit': 'banana', 'color': 'blue' }: 24,
{'fruit': 'apple', 'color': 'green'}: 12,
{'fruit': 'strawberry','color': 'blue' }: 0,
...
}
Chciałbym pobrać listę wszystkich niebieskich owoców, lub bananów wszystkich kolorów, na przykład, lub posortować ten słownik po nazwie owoc. Czy są sposoby, aby to zrobić w czysty sposób?
Może być tak, że słowniki z krotkami jako kluczami nie sąwłaściwym sposobem radzenia sobie z tą sytuacją.
Wszystkie propozycje mile widziane!
8 answers
Osobiście, jedną z rzeczy, które kocham w Pythonie, jest kombinacja tuple-dict. To, co tutaj masz, to tablica 2d (gdzie x = nazwa owocu i y = kolor), a ja generalnie jestem zwolennikiem słownika krotek do implementacji tablic 2d, przynajmniej gdy coś w rodzaju numpy
lub baza danych nie jest bardziej odpowiednie. Krótko mówiąc, myślę, że masz dobre podejście.
Zauważ, że nie możesz używać dict jako kluczy w dict bez dodatkowej pracy, więc nie jest to zbyt dobre rozwiązanie.
To powiedziawszy, powinieneś również rozważyć namedtuple () . W ten sposób można to zrobić:
>>> from collections import namedtuple
>>> Fruit = namedtuple("Fruit", ["name", "color"])
>>> f = Fruit(name="banana", color="red")
>>> print f
Fruit(name='banana', color='red')
>>> f.name
'banana'
>>> f.color
'red'
Teraz możesz użyć swojego fruitcount dict:
>>> fruitcount = {Fruit("banana", "red"):5}
>>> fruitcount[f]
5
Inne sztuczki:
>>> fruits = fruitcount.keys()
>>> fruits.sort()
>>> print fruits
[Fruit(name='apple', color='green'),
Fruit(name='apple', color='red'),
Fruit(name='banana', color='blue'),
Fruit(name='strawberry', color='blue')]
>>> fruits.sort(key=lambda x:x.color)
>>> print fruits
[Fruit(name='banana', color='blue'),
Fruit(name='strawberry', color='blue'),
Fruit(name='apple', color='green'),
Fruit(name='apple', color='red')]
Echo chmullig, aby uzyskać listę wszystkich kolorów jednego owocu, trzeba by filtrować klucze, tzn.
bananas = [fruit for fruit in fruits if fruit.name=='banana']
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-03 19:34:52
Najlepszym rozwiązaniem będzie stworzenie prostej struktury danych do modelowania tego, co masz. Następnie możesz przechowywać te obiekty w prostej liście i sortować/pobierać je w dowolny sposób.
W tym przypadku użyłbym następującej klasy:
class Fruit:
def __init__(self, name, color, quantity):
self.name = name
self.color = color
self.quantity = quantity
def __str__(self):
return "Name: %s, Color: %s, Quantity: %s" % \
(self.name, self.color, self.quantity)
Następnie można po prostu zbudować instancje "owocowe" i dodać je do listy, jak pokazano w następujący sposób:
fruit1 = Fruit("apple", "red", 12)
fruit2 = Fruit("pear", "green", 22)
fruit3 = Fruit("banana", "yellow", 32)
fruits = [fruit3, fruit2, fruit1]
Prosta lista fruits
będzie znacznie łatwiejsza, mniej myląca i lepiej utrzymana.
Niektóre przykłady użycia:
Wszystkie wyniki poniżej są wynikiem po uruchomieniu podanego fragmentu kodu, po którym następuje:
for fruit in fruits:
print fruit
lista niesortowana:
Wyświetla:
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Name: apple, Color: red, Quantity: 12
sortowane alfabetycznie według nazwy:
fruits.sort(key=lambda x: x.name.lower())
Wyświetla:
Name: apple, Color: red, Quantity: 12
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
sortowane według ilości:
fruits.sort(key=lambda x: x.quantity)
Wyświetla:
Name: apple, Color: red, Quantity: 12
Name: pear, Color: green, Quantity: 22
Name: banana, Color: yellow, Quantity: 32
gdzie color = = red:
red_fruit = filter(lambda f: f.color == "red", fruits)
Wyświetla:
Name: apple, Color: red, Quantity: 12
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-02 20:34:57
Baza danych, dict of dicts, słownik listy słowników, o nazwie tuple( to podklasa), sqlite, redundancja... Nie wierzyłem własnym oczom. Co jeszcze ?
Tak! Myślałem Więc moim zdaniem lista krotek wystarczy :" może być tak, że słowniki z krotkami jako kluczami nie są właściwym sposobem radzenia sobie z tą sytuacją."
"Mam przeczucie, że baza danych to przesada dla potrzeb OP;"
from operator import itemgetter
li = [ ('banana', 'blue' , 24) ,
('apple', 'green' , 12) ,
('strawberry', 'blue' , 16 ) ,
('banana', 'yellow' , 13) ,
('apple', 'gold' , 3 ) ,
('pear', 'yellow' , 10) ,
('strawberry', 'orange' , 27) ,
('apple', 'blue' , 21) ,
('apple', 'silver' , 0 ) ,
('strawberry', 'green' , 4 ) ,
('banana', 'brown' , 14) ,
('strawberry', 'yellow' , 31) ,
('apple', 'pink' , 9 ) ,
('strawberry', 'gold' , 0 ) ,
('pear', 'gold' , 66) ,
('apple', 'yellow' , 9 ) ,
('pear', 'brown' , 5 ) ,
('strawberry', 'pink' , 8 ) ,
('apple', 'purple' , 7 ) ,
('pear', 'blue' , 51) ,
('chesnut', 'yellow', 0 ) ]
print set( u[1] for u in li ),': all potential colors'
print set( c for f,c,n in li if n!=0),': all effective colors'
print [ c for f,c,n in li if f=='banana' ],': all potential colors of bananas'
print [ c for f,c,n in li if f=='banana' and n!=0],': all effective colors of bananas'
print
print set( u[0] for u in li ),': all potential fruits'
print set( f for f,c,n in li if n!=0),': all effective fruits'
print [ f for f,c,n in li if c=='yellow' ],': all potential fruits being yellow'
print [ f for f,c,n in li if c=='yellow' and n!=0],': all effective fruits being yellow'
print
print len(set( u[1] for u in li )),': number of all potential colors'
print len(set(c for f,c,n in li if n!=0)),': number of all effective colors'
print len( [c for f,c,n in li if f=='strawberry']),': number of potential colors of strawberry'
print len( [c for f,c,n in li if f=='strawberry' and n!=0]),': number of effective colors of strawberry'
print
# sorting li by name of fruit
print sorted(li),' sorted li by name of fruit'
print
# sorting li by number
print sorted(li, key = itemgetter(2)),' sorted li by number'
print
# sorting li first by name of color and secondly by name of fruit
print sorted(li, key = itemgetter(1,0)),' sorted li first by name of color and secondly by name of fruit'
print
Wynik
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange', 'silver']) : all potential colors
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange']) : all effective colors
['blue', 'yellow', 'brown'] : all potential colors of bananas
['blue', 'yellow', 'brown'] : all effective colors of bananas
set(['strawberry', 'chesnut', 'pear', 'banana', 'apple']) : all potential fruits
set(['strawberry', 'pear', 'banana', 'apple']) : all effective fruits
['banana', 'pear', 'strawberry', 'apple', 'chesnut'] : all potential fruits being yellow
['banana', 'pear', 'strawberry', 'apple'] : all effective fruits being yellow
9 : number of all potential colors
8 : number of all effective colors
6 : number of potential colors of strawberry
5 : number of effective colors of strawberry
[('apple', 'blue', 21), ('apple', 'gold', 3), ('apple', 'green', 12), ('apple', 'pink', 9), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'blue', 24), ('banana', 'brown', 14), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'blue', 51), ('pear', 'brown', 5), ('pear', 'gold', 66), ('pear', 'yellow', 10), ('strawberry', 'blue', 16), ('strawberry', 'gold', 0), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('strawberry', 'pink', 8), ('strawberry', 'yellow', 31)] sorted li by name of fruit
[('apple', 'silver', 0), ('strawberry', 'gold', 0), ('chesnut', 'yellow', 0), ('apple', 'gold', 3), ('strawberry', 'green', 4), ('pear', 'brown', 5), ('apple', 'purple', 7), ('strawberry', 'pink', 8), ('apple', 'pink', 9), ('apple', 'yellow', 9), ('pear', 'yellow', 10), ('apple', 'green', 12), ('banana', 'yellow', 13), ('banana', 'brown', 14), ('strawberry', 'blue', 16), ('apple', 'blue', 21), ('banana', 'blue', 24), ('strawberry', 'orange', 27), ('strawberry', 'yellow', 31), ('pear', 'blue', 51), ('pear', 'gold', 66)] sorted li by number
[('apple', 'blue', 21), ('banana', 'blue', 24), ('pear', 'blue', 51), ('strawberry', 'blue', 16), ('banana', 'brown', 14), ('pear', 'brown', 5), ('apple', 'gold', 3), ('pear', 'gold', 66), ('strawberry', 'gold', 0), ('apple', 'green', 12), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('apple', 'pink', 9), ('strawberry', 'pink', 8), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'yellow', 10), ('strawberry', 'yellow', 31)] sorted li first by name of color and secondly by name of fruit
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-02 13:05:29
Słownik prawdopodobnie nie jest tym, czego powinieneś używać w tym przypadku. Bardziej w pełni funkcjonalna biblioteka byłaby lepszą alternatywą. Pewnie prawdziwa baza danych. Najprostszym byłoby sqlite . Możesz zachować całość w pamięci, przekazując łańcuch ': memory: 'zamiast nazwy pliku.
Jeśli chcesz kontynuować tę ścieżkę, możesz to zrobić z dodatkowymi atrybutami w kluczu lub wartości. Jednak słownik nie może być kluczem do innego słownika, ale krotka może. dokumenty wyjaśniają, co jest dozwolone. Musi to być obiekt niezmienny, który zawiera ciągi znaków, Liczby i krotki, które zawierają tylko ciągi znaków i liczby (i więcej krotek zawierających tylko te typy rekurencyjnie...).
Możesz zrobić swój pierwszy przykład z d = {('apple', 'red') : 4}
, ale bardzo trudno będzie zapytać o to, czego chcesz. Musisz zrobić coś takiego:
#find all apples
apples = [d[key] for key in d.keys() if key[0] == 'apple']
#find all red items
red = [d[key] for key in d.keys() if key[1] == 'red']
#the red apple
redapples = d[('apple', 'red')]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-02 19:45:52
Z klawiszami jako krotkami, po prostu filtrujesz klucze z podanym drugim składnikiem i sortujesz:
blue_fruit = sorted([k for k in data.keys() if k[1] == 'blue'])
for k in blue_fruit:
print k[0], data[k] # prints 'banana 24', etc
Sortowanie działa, ponieważ krotki mają naturalną kolejność, jeśli ich komponenty mają naturalną kolejność.
Z kluczami jako pełnowartościowymi obiektami, po prostu filtrujesz według k.color == 'blue'
.
Tak naprawdę nie możesz używać dictów jako kluczy, ale możesz utworzyć najprostszą klasę, taką jak class Foo(object): pass
i dodać do niej dowolne atrybuty w locie:
k = Foo()
k.color = 'blue'
Te instancje mogą służyć jako klucze dict, ale uważaj na ich zmienność!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-02 20:03:10
Możesz mieć słownik, w którym wpisy są listą innych słowników:
fruit_dict = dict()
fruit_dict['banana'] = [{'yellow': 24}]
fruit_dict['apple'] = [{'red': 12}, {'green': 14}]
print fruit_dict
Wyjście:
{"banan": [{"żółty": 24}], "jabłko": [{"Czerwony": 12}, {"zielony": 14}]}
Edit: jak zauważył eumiro, przydałby się słownik słowników:
fruit_dict = dict()
fruit_dict['banana'] = {'yellow': 24}
fruit_dict['apple'] = {'red': 12, 'green': 14}
print fruit_dict
Wyjście:
{"banan": {"żółty": 24}, "jabłko": {"zielony": 14, "Czerwony": 12}}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-02 19:49:23
Ten typ danych jest efektywnie pobierany z Struktury Danych podobnej do Trie. Pozwala również na szybkie sortowanie. Wydajność pamięci może nie być tak duża.
Tradycyjny trie przechowuje każdą literę słowa jako węzeł w drzewie. Ale w Twoim przypadku twój "alfabet" jest inny. Zamiast znaków przechowujesz ciągi znaków.
Może wyglądać mniej więcej tak:
root: Root
/|\
/ | \
/ | \
fruit: Banana Apple Strawberry
/ | | \
/ | | \
color: Blue Yellow Green Blue
/ | | \
/ | | \
end: 24 100 12 0
Zobacz ten link: trie w Pythonie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:16
Chcesz używać dwóch klawiszy niezależnie, więc masz dwie opcje:
Przechowuj dane redundantnie za pomocą dwóch dictów jako
{'banana' : {'blue' : 4, ...}, .... }
i{'blue': {'banana':4, ...} ...}
. Następnie wyszukiwanie i sortowanie jest łatwe, ale musisz upewnić się, że zmodyfikowałeś dict razem.-
Przechowuj go tylko jeden dict, a następnie napisz funkcje, które nad nimi iterują np.:
d = {'banana' : {'blue' : 4, 'yellow':6}, 'apple':{'red':1} } blueFruit = [(fruit,d[fruit]['blue']) if d[fruit].has_key('blue') for fruit in d.keys()]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-07 19:38:44