在Python中按最大值子集化元组列表

Subset a list of tuples by max value in Python

我的问题是从这次讨论中产生的。我很抱歉,但由于我的水平,我无法在另一个答案下添加评论来问我的问题。我有这个元组列表:

1
my_list = [('Scaffold100019', 98310), ('Scaffold100019', 14807), ('Scaffold100425', 197577), ('Scaffold100636', 326), ('Scaffold10064', 85415), ('Scaffold10064', 94518)]

我想制作一个字典,它只存储定义为元组第一个元素的每个键的最大值:

1
my_dict = {'Scaffold100019': 98310, 'Scaffold100425': 197577, 'Scaffold100636': 326, 'Scaffold10064': 94518}

从马库斯·米勒的回答开始,我有:

1
2
3
4
5
6
7
8
9
d = {}

#build a dictionary of lists
for x,y in my_list: d.setdefault(x,[]).append(y)

my_dict = {}

#build a dictionary with the max value only
for item in d: my_dict[item] = max(d[item])

这样我就达到了我的目标,但是,有没有一种更圆滑的方式来完成这项任务?


我建议这个解决方案只有一个循环,可读性很强:

1
2
3
4
5
6
7
my_dict = {}

for x,y in my_list:
    if x in my_dict.keys():
        my_dict [x] = max (y, my_dict [x])
    else:
        my_dict [x] = y


你可以使用collections.defaultdict

1
2
3
4
5
from collections import defaultdict

d = defaultdict(int)
for key, value in my_list:
    d[key] = max(d[key], value)

上面的代码适用于您的示例数据,但一般情况下,只有当每个键的最大值为非负值时才有效。这是因为当没有设置值时,defaultdict(int)返回零,因此如果给定键的所有值都为负数,则结果max将错误地为零。

如果给定的键可以使用纯负值,则可以进行以下更改:

1
d = defaultdict(lambda: -float('inf'))

通过这种改变,在没有设置键的情况下,将返回负无穷大,因此负值不再是一个问题。


使用所有内容都大于None和字典get方法的事实,其中None作为回退返回值。

1
2
3
4
5
6
7
>>> d = {}
>>> for name, value in my_list:
...     if value > d.get(name, None):
...         d[name] = value
...
>>> d
{'Scaffold100425': 197577, 'Scaffold10064': 94518, 'Scaffold100019': 98310, 'Scaffold100636': 326}

对于所有值和哈希,每个循环最多两次。