在Python字典中存储和更新列表:这为什么会发生?

27 投票
4 回答
94195 浏览
提问于 2025-04-11 20:56

我有一份数据列表,长得像这样:

// timestep,x_position,y_position
0,4,7
0,2,7
0,9,5
0,6,7
1,2,5
1,4,7
1,9,0
1,6,8

... 我想把它变成这样:

0, (4,7), (2,7), (9,5), (6,7)
1, (2,5), (4,7), (9,0), (6.8)

我的计划是用一个字典,字典里的键是 t 的值,而对应这个键的值是一个列表。然后我可以把每个 (x,y) 加到这个列表里。大概是这样的:

# where t = 0, c = (4,7), d = {}

# code 1
d[t].append(c)

现在这样做会让 IDLE 出错。不过,如果我这样做:

# code 2
d[t] = []
d[t].append(c)

... 这样就没问题了。

所以问题是:为什么代码 2 能工作,而代码 1 不行呢?

附注:如果你对我计划的做法有什么改进建议,我会很感兴趣!我想我需要在每次循环输入的时候检查字典,看看这个字典的键是否已经存在。我想可以用类似 max(d.keys()) 的方法:如果存在,就添加数据;如果不存在,就创建一个空列表作为字典的值,然后在下一次循环时再添加数据。

4 个回答

1

如果你的数据还没有按照你想要的标准排序,下面的代码可能会帮助你把数据分组:

#!/usr/bin/env python
"""
$ cat data_shuffled.txt
0,2,7
1,4,7
0,4,7
1,9,0
1,2,5
0,6,7
1,6,8
0,9,5
"""
from itertools   import groupby
from operator    import itemgetter

# load the data and make sure it is sorted by the first column
sortby_key = itemgetter(0)
data = sorted((map(int, line.split(',')) for line in open('data_shuffled.txt')),
              key=sortby_key)

# group by the first column
grouped_data = []
for key, group in groupby(data, key=sortby_key):
    assert key == len(grouped_data) # assume the first column is 0,1, ...
    grouped_data.append([trio[1:] for trio in group])

# print the data
for i, pairs in enumerate(grouped_data):
    print i, pairs

输出结果:

0 [[2, 7], [4, 7], [6, 7], [9, 5]]
1 [[4, 7], [9, 0], [2, 5], [6, 8]]
12

我觉得你可以用 setdefault 这个方法。虽然它有点奇怪,但正好能满足你的需求。

d.setdefault(t, []).append(c)

.setdefault 这个方法会检查字典里有没有你指定的键 t。如果有,它就会返回和这个键关联的元素(在我们这个例子里是一个列表)。如果没有,它会给这个键 t 绑定一个空列表,并返回这个空列表。这样无论如何,都会有一个列表,接下来你就可以用 .append 方法把元组 c 加进去。

73

我们来看看

d[t].append(c)

d[t]的值是什么?试试看。

d = {}
t = 0
d[t]

你得到了什么?哦,d里没有键为t的东西。

现在试试这个。

d[t] = []
d[t]

啊,现在d里有键为t的东西了。

你可以做几件事:

  1. 使用示例2。
  2. 使用setdefault。可以这样写:d.setdefault(t,[]).append(c)
  3. 使用collections.defaultdict。你可以用defaultdict(list)来代替普通字典{}

编辑 1. 优化

给定来自文件的输入行,格式为:ts, x, y,分组过程是多余的。没有必要把简单的列表(ts, x, y)变成更复杂的列表(ts, (x,y), (x,y), (x,y), ...)。原始列表可以直接处理。

d= collections.defaultdict(list)
for ts, x, y in someFileOrListOrQueryOrWhatever:
    d[ts].append( (x,y) )

编辑 2. 回答问题

“在初始化字典时,你需要告诉字典键值数据结构会是什么样子吗?”

我不太明白这个问题的意思。因为所有字典本身就是键值结构,所以这个问题不太清楚。因此,我会回顾三种选择,可能能回答这个问题。

示例 2

初始化

d= {}

使用

if t not in d:
    d[t] = list()
d[t].append( c )

每个字典的值必须初始化为某种有用的结构。在这种情况下,我们检查键是否存在;当键缺失时,我们创建这个键并赋值为空列表。

Setdefault

初始化

d= {}

使用

d.setdefault(t,list()).append( c )

在这种情况下,我们利用setdefault方法来获取与某个键相关联的值,或者为缺失的键创建一个新的值。

默认字典

初始化

import collections
d = collections.defaultdict(list)

使用

d[t].append( c )

defaultdict为缺失的键使用初始化函数。在这种情况下,我们提供list函数,以便为缺失的键创建一个新的空列表。

撰写回答