163

我是 python 新手,我有一个每年的年份和值的列表。我想要做的是检查字典中是否已经存在年份,如果存在,则将该值附加到特定键的值列表中。

例如,我有一个年份列表,并且每年都有一个值:

2010  
2  
2009  
4  
1989  
8  
2009  
7  

我想要做的是用年份作为键和那些个位数作为值来填充字典。但是,如果我两次列出了 2009,我想将第二个值附加到我在该字典中的值列表中,所以我想要:

2010: 2  
2009: 4, 7  
1989: 8  

现在我有以下内容:

d = dict()  
years = []  

(get 2 column list of years and values)

for line in list:    
    year = line[0]   
    value = line[1]  

for line in list:  
    if year in d.keys():  
        d[value].append(value)  
    else:  
        d[value] = value  
        d[year] = year  
4

7 回答 7

231

如果我可以改写您的问题,您想要的是一个以年份为键的字典和一个包含与该年份关联的值列表的每年的数组,对吗?这是我的做法:

years_dict = dict()

for line in list:
    if line[0] in years_dict:
        # append the new number to the existing array at this slot
        years_dict[line[0]].append(line[1])
    else:
        # create a new array in this slot
        years_dict[line[0]] = [line[1]]

您最终应该在 years_dict 中得到一个字典,如下所示:

{
    "2010": [2],
    "2009": [4,7],
    "1989": [8]
}

通常,创建“并行数组”是一种糟糕的编程实践,其中项通过具有相同的索引而不是包含它们的容器的适当子项而隐式地相互关联。

于 2010-07-07T22:00:52.907 回答
117

你最好使用collections.defaultdict(在 Python 2.5 中添加)。这允许您指定缺失键的默认对象类型(例如 a list)。

因此,与其先创建一个不存在的键,然后附加到键的值,不如去掉中间人,直接附加到不存在的键以获得所需的结果。

使用您的数据的快速示例:

>>> from collections import defaultdict
>>> data = [(2010, 2), (2009, 4), (1989, 8), (2009, 7)]
>>> d = defaultdict(list)
>>> d
defaultdict(<type 'list'>, {})
>>> for year, month in data:
...     d[year].append(month)
... 
>>> d
defaultdict(<type 'list'>, {2009: [4, 7], 2010: [2], 1989: [8]})

这样您就不必担心是否看到与年份相关的数字。您只需追加并忘记,知道丢失的键将始终是一个列表。如果密钥已经存在,那么它将被附加到。

于 2010-07-07T21:53:56.590 回答
56

您可以使用setdefault.

for line in list:  
    d.setdefault(year, []).append(value)

这是有效的,因为 setdefault 返回列表并将其设置在字典中,并且由于列表是可变的,附加到 setdefault 返回的版本与将其附加到字典本身内的版本相同。如果那有意义的话。

于 2010-07-07T22:00:17.230 回答
26
d = {} 

# import list of year,value pairs

for year,value in mylist:
    try:
        d[year].append(value)
    except KeyError:
        d[year] = [value]

Python 方式 - 获得宽恕比请求许可更容易!

于 2010-07-09T12:52:50.550 回答
17

这是使用not in运算符执行此操作的另一种方法:

# define an empty dict
years_dict = dict()

for line in list:
    # here define what key is, for example,
    key = line[0]
    # check if key is already present in dict
    if key not in years_dict:
        years_dict[key] = []
    # append some value 
    years_dict[key].append(some.value)
于 2016-10-17T10:47:21.467 回答
7

如果将这些值放入元组列表中会更容易。为此,您可以使用列表切片和 zip 功能。

data_in = [2010,2,2009,4,1989,8,2009,7]
data_pairs = zip(data_in[::2],data_in[1::2])

Zip 接受任意数量的列表,在本例中是 的偶数和奇数条目data_in,并将它们放在一起形成一个元组。

现在我们可以使用该setdefault方法了。

data_dict = {}
for x in data_pairs:
    data_dict.setdefault(x[0],[]).append(x[1])

setdefault接受一个键和一个默认值,并返回关联的值,或者如果没有当前值,则返回默认值。在这种情况下,我们将获得一个空列表或填充列表,然后将当前值附加到该列表中。

于 2012-12-11T21:17:53.327 回答
3

如果您想要(几乎)单线:

从集合导入双端队列

d = {}
deque((d.setdefault(year, []).append(value) for year, source_of_data 中的值), maxlen=0)

Using dict.setdefault, you can encapsulate the idea of "check if the key already exists and make a new list if not" into a single call. This allows you to write a generator expression which is consumed by deque as efficiently as possible since the queue length is set to zero. The deque will be discarded immediately and the result will be in d.

This is something I just did for fun. I don't recommend using it. There is a time and a place to consume arbitrary iterables through a deque, and this is definitely not it.

于 2017-11-25T13:31:47.257 回答