Python: кортежи / словари в качестве ключей, выберите, отсортируйте

предположим, что у меня есть количество плодов разных цветов, например, 24 синих банана, 12 зеленых яблок, 0 синяя клубника и так далее. Я хотел бы организовать их в структуре данных в Python, что позволяет легко выбирать и сортировать. Моя идея заключалась в том, чтобы поместить их в словарь с кортежами в качестве ключей, например,

{ ('banana', 'blue' ): 24, ('apple', 'green'): 12, ('strawberry','blue' ): 0, ... } 

или даже словарей, например,

 { {'fruit': 'banana', 'color': 'blue' }: 24, {'fruit': 'apple', 'color': 'green'}: 12, {'fruit': 'strawberry','color': 'blue' }: 0, ... } 

Например, я хотел бы получить список всех синих фруктов или бананов всех цветов или отсортировать этот словарь по названию фрукта. Есть ли способы сделать это чистым способом?

Вполне возможно, что словари с кортежами в качестве ключей не являются надлежащим способом справиться с этой ситуацией.

Все предложения приветствуются!

8 Solutions collect form web for “Python: кортежи / словари в качестве ключей, выберите, отсортируйте”

Лично одна из вещей, которые мне нравятся в python, – комбинация кортежей-диктов. То, что у вас здесь, представляет собой массив 2d (где x = имя плода и y = цвет), и я, как правило, сторонник диктатуры кортежей для реализации 2d-массивов, по крайней мере, когда что-то вроде numpy или базы данных не больше подходящее. Короче говоря, я думаю, что у вас есть хороший подход.

Обратите внимание, что вы не можете использовать dicts как ключи в dict без дополнительной работы, так что это не очень хорошее решение.

Тем не менее, вы должны также рассмотреть namedtuple () . Таким образом, вы можете это сделать:

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

Теперь вы можете использовать свой speccount:

 >>> fruitcount = {Fruit("banana", "red"):5} >>> fruitcount[f] 5 

Другие трюки:

 >>> 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')] 

Повторяя chmullig, чтобы получить список всех цветов одного плода, вам придется отфильтровать ключи, т. Е.

 bananas = [fruit for fruit in fruits if fruit.name=='banana'] 

Ваш лучший вариант – создать простую структуру данных для моделирования того, что у вас есть. Затем вы можете хранить эти объекты в простом списке и сортировать / извлекать их любым способом.

В этом случае я бы использовал следующий класс:

 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) 

Затем вы можете просто создать экземпляры «Fruit» и добавить их в список, как показано ниже:

 fruit1 = Fruit("apple", "red", 12) fruit2 = Fruit("pear", "green", 22) fruit3 = Fruit("banana", "yellow", 32) fruits = [fruit3, fruit2, fruit1] 

Простой список fruits будет намного проще, менее запутанным и лучше поддерживать.

Некоторые примеры использования:

Все выходы ниже – результат после запуска данного фрагмента кода, за которым следуют:

 for fruit in fruits: print fruit 

Не отсортированный список:

Вывод:

 Name: banana, Color: yellow, Quantity: 32 Name: pear, Color: green, Quantity: 22 Name: apple, Color: red, Quantity: 12 

Сортировка по алфавиту по названию:

 fruits.sort(key=lambda x: x.name.lower()) 

Вывод:

 Name: apple, Color: red, Quantity: 12 Name: banana, Color: yellow, Quantity: 32 Name: pear, Color: green, Quantity: 22 

Отсортировано по количеству:

 fruits.sort(key=lambda x: x.quantity) 

Вывод:

 Name: apple, Color: red, Quantity: 12 Name: pear, Color: green, Quantity: 22 Name: banana, Color: yellow, Quantity: 32 

Где цвет == красный:

 red_fruit = filter(lambda f: f.color == "red", fruits) 

Вывод:

 Name: apple, Color: red, Quantity: 12 

База данных, dict of dicts, словарь списка словарей, названный кортеж (это подкласс), sqlite, избыточность … Я не верил своим глазам. Что еще ?

«Вполне возможно, что словари с кортежами в качестве ключей не являются надлежащим способом справиться с этой ситуацией».

«мое чувство кишки заключается в том, что база данных излишняя для потребностей 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 

результат

 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 

Словарь, вероятно, не тот, который вы должны использовать в этом случае. Лучшей альтернативой станет более полнофункциональная библиотека. Вероятно, настоящая база данных. Самый простой был бы sqlite . Вы можете сохранить все это в памяти, передав в строке «: memory:» вместо имени файла.

Если вы хотите продолжить этот путь, вы можете сделать это с дополнительными атрибутами в ключе или значении. Однако словарь не может быть ключом к другому словарю, но кортеж может. Документы объясняют, что допустимо. Он должен быть неизменным объектом, который включает в себя строки, числа и кортежи, которые содержат только строки и числа (и больше кортежей, содержащих только эти типы, рекурсивно …).

Вы можете сделать свой первый пример с d = {('apple', 'red') : 4} , но будет очень сложно запросить то, что вы хотите. Вам нужно будет сделать что-то вроде этого:

 #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')] 

У вас может быть словарь, в котором записи представляют собой список других словарей:

 fruit_dict = dict() fruit_dict['banana'] = [{'yellow': 24}] fruit_dict['apple'] = [{'red': 12}, {'green': 14}] print fruit_dict 

Вывод:

{'banana': [{'yellow': 24}], 'apple': [{'red': 12}, {'green': 14}]}

Изменить: Как отметил Эумиро, вы можете использовать словарь словарей:

 fruit_dict = dict() fruit_dict['banana'] = {'yellow': 24} fruit_dict['apple'] = {'red': 12, 'green': 14} print fruit_dict 

Вывод:

{'banana': {'yellow': 24}, 'apple': {'green': 14, 'red': 12}}

С ключами в качестве кортежей вы просто отфильтровываете ключи с заданным вторым компонентом и сортируете его:

 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 

Сортировка работает, потому что кортежи имеют естественный порядок, если их компоненты имеют естественный порядок.

С ключами, как довольно полнофункциональными объектами, вы просто фильтруете k.color == 'blue' .

Вы не можете использовать dicts как ключи, но вы можете создать простейший класс, например class Foo(object): pass и добавить к нему любые атрибуты «на лету»:

 k = Foo() k.color = 'blue' 

Эти экземпляры могут служить в качестве ключей dict, но остерегайтесь их изменчивости!

Этот тип данных эффективно извлекается из структуры данных типа Trie. Это также позволяет быстро сортировать. Однако эффективность памяти может быть не такой уж большой.

Традиционная trie хранит каждую букву слова как узел в дереве. Но в вашем случае ваш «алфавит» отличается. Вы сохраняете строки вместо символов.

это может выглядеть примерно так:

 root: Root /|\ / | \ / | \ fruit: Banana Apple Strawberry / | | \ / | | \ color: Blue Yellow Green Blue / | | \ / | | \ end: 24 100 12 0 

см. эту ссылку: trie in python

Вы хотите использовать два ключа самостоятельно, поэтому у вас есть два варианта:

  1. Храните данные избыточно с двумя dicts как {'banana' : {'blue' : 4, ...}, .... } и {'blue': {'banana':4, ...} ...} . Затем поиск и сортировка просты, но вы должны убедиться, что вы модифицируете dicts вместе.

  2. Сохраните его только один dict, а затем напишите функции, которые перебирают их, например:

     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()] 
  • Как запросить для всех групп типа 'foo', которые содержат user_x? (таблица «многие-ко-многим»)
  • Поле Django Multiple Choice / Checkbox Выберите несколько
  • элегантно разбивая список (или dict) на два через какую-то произвольную функцию в python
  • Выберите строки из Numpy Rec Array
  • Поддерживает ли метод BeautifulSoup .select () использование регулярного выражения?
  • Python, Popen и select - ожидание завершения процесса или тайм-аута
  •  
    Interesting Posts for Van-Lav

    Как затенять под кривой в matplotlib, но с переменной цветной альфой?

    Ошибка потока в Python & PyQt

    Сплит models.py в несколько файлов

    Django: Как перенаправить на страницу, откуда возникла форма?

    Музыкальная библиотека Python?

    Декодер Python для обеспечения правильности kwargs

    Неперекрывающееся совпадение шаблонов с ограничением пробелов в python

    Почему Python, похоже, рассматривает переменные экземпляра как общие между объектами?

    Как изменить разрешение .tif растрового файла без потери данных

    Использование алгоритма SlopeOne для прогнозирования, может ли геймер заполнить уровень в игре?

    ALTER TABLE Sqlite: как проверить, существует ли столбец перед изменением таблицы?

    Python – как читать файл с NUL-разделителями?

    Как получить имя файла и lineno атрибута SyntaxError

    Python версии 2.7: XML ElementTree: как выполнять итерацию через определенные элементы дочернего элемента, чтобы найти совпадение

    Chunking с nltk

    Python - лучший язык программирования в мире.