1.6 Associating Multiple Values with Each Key in a Dictionary
在字典里把每一个键同多个值关联起来
Credit: Michael Chermside
1.6.1 Problem
问题
You need a dictionary that maps each key to multiple values.
你需要一个映射每个键到多个值的字典。
1.6.2 Solution
解决
By nature, a dictionary is a one-to-one mapping, but it's not hard to make it one-to-many梚n other words, to make one key map to multiple values. There are two possible approaches, depending on how you want to treat duplications in the set of values for a key. The following approach allows such duplications:
默认地,一个字典是一对一的映射。但是一对多也不是很困难,让一个键映射多个值就可以了:
d1 = {}
d1.setdefault(key, []).append(value)
while this approach automatically eliminates duplications:
这个方法自动地除去重复的项。
d2 = {}
d2.setdefault(key, {})[value] = 1
1.6.3 Discussion
讨论
A normal dictionary performs a simple mapping of a key to a value. This recipe shows two easy, efficient ways to achieve a mapping of each key to multiple values. The semantics of the two approaches differ slightly but importantly in how they deal with duplication. Each approach relies on the setdefault method of a dictionary to initialize the entry for a key in the dictionary, if needed, and in any case to return said entry.
一个正常的字典执行一个简单的一个键对应一个值的映射。这个配方显示两种简单,有效的方法让一个键对应多个值。两种方法的语义稍微有点不同。 但是重要的是他们怎样处理重复的项。每个方法依赖于字典的setdefault方法去为一个键初始化入口。并且,如果需要,无论如何都会返回上述的入口。
Of course, you need to be able to do more than just add values for a key. With the first approach, which allows duplications, here's how to retrieve the list of values for a key:
当然,你需要能够做的比仅仅为一个键增加一个值更多。 对于第一种方法,它允许有重复的键,这儿是怎样为一个键去获取值的列表:
list_of_values = d1[key]
Here's how to remove one value for a key, if you don't mind leaving empty lists as items of d1 when the last value for a key is removed:
这是怎样为一个键移除一个值,如果你不关心一个键的最后的值被移走时,留下的空列表作为d2的元素:
d1[key].remove(value)
Despite the empty lists, it's still easy to test for the existence of a key with at least one value:
不管空列表,它仍然很容易去测试至少有一个值的键的存在:
def has_key_with_some_values(d, key):
return d.has_key(key) and d[key]
This returns either 0 or a list, which may be empty. In most cases, it is easier to use a function that always returns a list (maybe an empty one), such as:
它返回0或者一个列表,这个列表或许是空的。在大多数情况下,很容易使用一个一直返回一个列表(会许是一个空的)的函数,诸如:
def get_values_if_any(d, key):
return d.get(key, [])
You can use either of these functions in a statement. For example:
你能在一个语句里使用这些函数中的任何一个,例如
if get_values_if_any(d1, somekey):
if has_key_with_some_values(d1, somekey):
However, get_values_if_any is generally handier. For example, you can use it to check if 'freep' is among the values for somekey:
然而,get_values_if_any是更方便些。例如,你能使用它检查'freep'是否是一些键所对应值的一个
if 'freep' in get_values_if_any(d1, somekey):
This extra handiness comes from get_values_if_any always returning a list, rather than sometimes a list and sometimes 0.
这种便利来自于get_values_if_any 一直返回一个列表而不是有时候返回一个列表,有时候返回0
The first approach allows each value to be present multiple times for each given key. For example:
第一种方法允许每个值可以为每个被给的键表示多次,例如
example = {}
example.setdefault('a', []).append('apple')
example.setdefault('b', []).append('boots')
example.setdefault('c', []).append('cat')
example.setdefault('a', []).append('ant')
example.setdefault('a', []).append('apple')
Now example['a'] is ['apple', 'ant', 'apple']. If we now execute:
现在, example['a']是['apple', 'ant', 'apple']。 如果我们现在执行:
example['a'].remove('apple')
the following test is still satisfied:
下面的测试仍然是令人满意的
if 'apple' in example['a']
'apple' was present twice, and we removed it only once. (Testing for 'apple' with get_values_if_any(example, 'a') would be more general, although equivalent in this case.)
'apple'出现两次,并且我们仅仅移除一次。(为'apple', 做get_values_if_any(example, 'a')测试尽管相当于这种情况,但是更具普遍性)
The second approach, which eliminates duplications, requires rather similar idioms. Here's how to retrieve the list of the values for a key:
第二种方法,它消除重复,需要更合适的类似的惯用方法。这里是怎么样为一个键获得值的列表:
list_of_values = d2[key].keys( )
Here's how to remove a key/value pair, leaving empty dictionaries as items of d2 when the last value for a key is removed:
这里是怎么样移除一个键/值对,当这个键的最后一个值被除掉的时候,留下空的字典最为d2的元素:
del d2[key][value]
The has_key_with_some_values function shown earlier also works for the second approach, and you also have analogous alternatives, such as:
has_key_with_some_values 函数象更早显示的那样为第二种方法工作,你也有一个相似的选择,诸如:
def get_values_if_any(d, key):
return d.get(key, {}).keys( )
The second approach doesn't allow duplication. For example:
第二种方法不允许重复,例如
example = {}
example.setdefault('a', {})['apple']=1
example.setdefault('b', {})['boots']=1
example.setdefault('c', {})['cat']=1
example.setdefault('a', {})['ant']=1
example.setdefault('a', {})['apple']=1
Now example['a'] is {'apple':1, 'ant':1}. Now, if we execute:
现在example['a'] 是 {'apple':1, 'ant':1}。 现在,如果我们执行:
del example['a']['apple']
the following test is not satisfied:
下面的测试不能令人满意:
if 'apple' in example['a']
'apple' was present, but we just removed it.
'apple'出现,但是我们仅仅移除它。
This recipe focuses on how to code the raw functionality, but if you want to use this functionality in a systematic way, you'll want to wrap it up in a class. For that purpose, you need to make some of the design decisions that the recipe highlights. Do you want a value to be in the entry for a key multiple times? (Is the entry a bag rather than a set, in mathematical terms?) If so, should remove just reduce the number of occurrences by 1, or should it wipe out all of them? This is just the beginning of the choices you have to make, and the right choices depend on the specifics of your application.
这个配方关注怎么样编写原始的功能,但是如果你想在一个语法途径上使用这种功能,你将在一个类里包装它。为了那样的目的,你需要做一些设计决 策来加强这个配方。你想一个在入口的值对应一个键多次吗?(对精确的术语来说,入口是一个包而不是一个集合?)如果是这样,应该是移除仅仅让重复的值的数 目减少一个,或者是应该把他们全部消灭?这个是你不得不作出选择的开始,并且正确的选择依赖于你的特定的应用。
1.6.4 See Also
参考
The Library Reference section on mapping types.
[转]在字典里把每一个键同多个值关联起来
最新推荐文章于 2024-05-22 15:32:45 发布