Python:元组/字典作为键,选择,排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4878881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: Tuples/dictionaries as keys, select, sort
提问by Nico Schl?mer
suppose I have quantities of fruits of different colors, e.g., 24 blue bananas, 12 green apples, 0 blue strawberries and so on. I'd like to organize them in a data structure in Python that allows for easy selection and sorting. My idea was to put them into a dictionary with tuples as keys, e.g.,
假设我有大量不同颜色的水果,例如,24 个蓝色香蕉、12 个青苹果、0 个蓝色草莓等等。我想将它们组织在 Python 中的数据结构中,以便于选择和排序。我的想法是将它们放入以元组为键的字典中,例如,
{ ('banana', 'blue' ): 24,
('apple', 'green'): 12,
('strawberry','blue' ): 0,
...
}
or even dictionaries, e.g.,
甚至是字典,例如,
{ {'fruit': 'banana', 'color': 'blue' }: 24,
{'fruit': 'apple', 'color': 'green'}: 12,
{'fruit': 'strawberry','color': 'blue' }: 0,
...
}
I'd like to retrieve a list of all blue fruit, or bananas of all colors, for example, or to sort this dictionary by the name of the fruit. Are there ways to do this in a clean way?
例如,我想检索所有蓝色水果或所有颜色香蕉的列表,或者按水果名称对本词典进行排序。有没有办法以干净的方式做到这一点?
It might well be that dictionaries with tuples as keys are not the properway to handle this situation.
以元组为键的字典很可能不是处理这种情况的正确方法。
All suggestions welcome!
欢迎所有建议!
采纳答案by senderle
Personally, one of the things I love about python is the tuple-dict combination. What you have here is effectively a 2d array (where x = fruit name and y = color), and I am generally a supporter of the dict of tuples for implementing 2d arrays, at least when something like numpyor a database isn't more appropriate. So in short, I think you've got a good approach.
就我个人而言,我喜欢 python 的一件事是元组-字典组合。您在此处拥有的实际上是一个二维数组(其中 x = 水果名称和 y = 颜色),并且我通常支持用于实现二维数组的元组字典,至少在类似numpy或数据库不适合的情况下. 简而言之,我认为你有一个很好的方法。
Note that you can't use dicts as keys in a dict without doing some extra work, so that's not a very good solution.
请注意,您不能在不做一些额外工作的情况下将 dicts 用作 dict 中的键,因此这不是一个很好的解决方案。
That said, you should also consider namedtuple(). That way you could do this:
也就是说,您还应该考虑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'
Now you can use your fruitcount dict:
现在你可以使用你的fruitcount dict:
>>> fruitcount = {Fruit("banana", "red"):5}
>>> fruitcount[f]
5
Other tricks:
其他技巧:
>>> 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')]
Echoing chmullig, to get a list of all colors of one fruit, you would have to filter the keys, i.e.
回应 chmullig,要获得一个水果的所有颜色的列表,您必须过滤键,即
bananas = [fruit for fruit in fruits if fruit.name=='banana']
回答by highBandWidth
You want to use two keys independently, so you have two choices:
你想独立使用两个键,所以你有两个选择:
Store the data redundantly with two dicts as
{'banana' : {'blue' : 4, ...}, .... }and{'blue': {'banana':4, ...} ...}. Then, searching and sorting is easy but you have to make sure you modify the dicts together.Store it just one dict, and then write functions that iterate over them eg.:
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()]
使用两个字典将数据冗余存储为
{'banana' : {'blue' : 4, ...}, .... }and{'blue': {'banana':4, ...} ...}。然后,搜索和排序很容易,但您必须确保一起修改字典。只存储一个字典,然后编写迭代它们的函数,例如:
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()]
回答by GreenMatt
You could have a dictionary where the entries are a list of other dictionaries:
你可以有一个字典,其中的条目是其他字典的列表:
fruit_dict = dict()
fruit_dict['banana'] = [{'yellow': 24}]
fruit_dict['apple'] = [{'red': 12}, {'green': 14}]
print fruit_dict
Output:
输出:
{'banana': [{'yellow': 24}], 'apple': [{'red': 12}, {'green': 14}]}
{'香蕉':[{'黄色':24}],'苹果':[{'红色':12},{'绿色':14}]}
Edit: As eumiro pointed out, you could use a dictionary of dictionaries:
编辑:正如 eumiro 所指出的,您可以使用字典字典:
fruit_dict = dict()
fruit_dict['banana'] = {'yellow': 24}
fruit_dict['apple'] = {'red': 12, 'green': 14}
print fruit_dict
Output:
输出:
{'banana': {'yellow': 24}, 'apple': {'green': 14, 'red': 12}}
{'香蕉':{'黄色':24},'苹果':{'绿色':14,'红色':12}}
回答by chmullig
A dictionary probably isn't what you should be using in this case. A more full featured library would be a better alternative. Probably a real database. The easiest would be sqlite. You can keep the whole thing in memory by passing in the string ':memory:' instead of a filename.
在这种情况下,字典可能不是您应该使用的。功能更齐全的库将是更好的选择。可能是一个真正的数据库。最简单的是sqlite。您可以通过传入字符串 ':memory:' 而不是文件名来将整个内容保存在内存中。
If you do want to continue down this path, you can do it with the extra attributes in the key or the value. However a dictionary can't be the key to a another dictionary, but a tuple can. The docsexplain what's allowable. It must be an immutable object, which includes strings, numbers and tuples that contain only strings and numbers (and more tuples containing only those types recursively...).
如果您确实想继续沿着这条路走下去,您可以使用键或值中的额外属性来实现。然而,字典不能是另一个字典的键,但元组可以。文档解释了什么是允许的。它必须是一个不可变对象,包括字符串、数字和只包含字符串和数字的元组(以及更多只包含这些类型的元组递归......)。
You could do your first example with d = {('apple', 'red') : 4}, but it'll be very hard to query for what you want. You'd need to do something like this:
你可以用 做你的第一个例子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')]
回答by 9000
With keys as tuples, you just filter the keys with given second component and sort it:
使用键作为元组,您只需使用给定的第二个组件过滤键并对其进行排序:
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
Sorting works because tuples have natural ordering if their components have natural ordering.
排序之所以有效,是因为如果元组的组件具有自然排序,则元组具有自然排序。
With keys as rather full-fledged objects, you just filter by k.color == 'blue'.
将键作为相当成熟的对象,您只需按k.color == 'blue'.
You can't really use dicts as keys, but you can create a simplest class like class Foo(object): passand add any attributes to it on the fly:
您不能真正使用 dicts 作为键,但您可以创建一个最简单的类,例如class Foo(object): pass并动态添加任何属性:
k = Foo()
k.color = 'blue'
These instances can serve as dict keys, but beware their mutability!
这些实例可以用作字典键,但要注意它们的可变性!
回答by Cuga
Your best option will be to create a simple data structure to model what you have. Then you can store these objects in a simple list and sort/retrieve them any way you wish.
您最好的选择是创建一个简单的数据结构来对您拥有的内容进行建模。然后您可以将这些对象存储在一个简单的列表中,并以您希望的任何方式对它们进行排序/检索。
For this case, I'd use the following class:
对于这种情况,我将使用以下类:
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)
Then you can simply construct "Fruit" instances and add them to a list, as shown in the following manner:
然后您可以简单地构建“Fruit”实例并将它们添加到列表中,如下所示:
fruit1 = Fruit("apple", "red", 12)
fruit2 = Fruit("pear", "green", 22)
fruit3 = Fruit("banana", "yellow", 32)
fruits = [fruit3, fruit2, fruit1]
The simple list fruitswill be much easier, less confusing, and better-maintained.
简单的列表fruits会更容易、更少混淆并且更好维护。
Some examples of use:
一些使用示例:
All outputs below is the result after running the given code snippet followed by:
下面的所有输出都是运行给定代码片段后的结果,后跟:
for fruit in fruits:
print fruit
Unsorted list:
未分类列表:
Displays:
显示:
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Name: apple, Color: red, Quantity: 12
Sorted alphabetically by name:
按名称字母顺序排序:
fruits.sort(key=lambda x: x.name.lower())
Displays:
显示:
Name: apple, Color: red, Quantity: 12
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Sorted by quantity:
按数量排序:
fruits.sort(key=lambda x: x.quantity)
Displays:
显示:
Name: apple, Color: red, Quantity: 12
Name: pear, Color: green, Quantity: 22
Name: banana, Color: yellow, Quantity: 32
Where color == red:
其中颜色 == 红色:
red_fruit = filter(lambda f: f.color == "red", fruits)
Displays:
显示:
Name: apple, Color: red, Quantity: 12
回答by eyquem
Database, dict of dicts, dictionary of list of dictionaries, named tuple (it's a subclass), sqlite, redundancy... I didn't believe my eyes. What else ?
数据库,字典的字典,字典列表的字典,命名元组(它是一个子类),sqlite,冗余......我不相信自己的眼睛。还有什么 ?
"It might well be that dictionaries with tuples as keys are not the proper way to handle this situation."
"my gut feeling is that a database is overkill for the OP's needs; "
“很可能以元组为键的字典不是处理这种情况的正确方法。”
“我的直觉是,数据库对于 OP 的需求来说太过分了;”
Yeah! I thought
是的!我想
So, in my opinion, a list of tuples is plenty enough :
所以,在我看来,一个元组列表就足够了:
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
result
结果
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
回答by Scott Morken
This type of data is efficiently pulled from a Trie-like data structure. It also allows for fast sorting. The memory efficiency might not be that great though.
这种类型的数据是从类似 Trie 的数据结构中有效提取的。它还允许快速排序。不过内存效率可能不是那么好。
A traditional trie stores each letter of a word as a node in the tree. But in your case your "alphabet" is different. You are storing strings instead of characters.
传统的 trie 将单词的每个字母存储为树中的一个节点。但在你的情况下,你的“字母表”是不同的。您正在存储字符串而不是字符。
it might look something like this:
它可能看起来像这样:
root: Root
/|\
/ | \
/ | \
fruit: Banana Apple Strawberry
/ | | \
/ | | \
color: Blue Yellow Green Blue
/ | | \
/ | | \
end: 24 100 12 0
see this link: trie in python
请参阅此链接:在 python 中尝试

