使用相同的密钥从dict.values()获取最大值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用相同的密钥从dict.values()获取最大值相关的知识,希望对你有一定的参考价值。

我有这个csv.file。假设我已经使用过DictReader,现在我有一些列表,如('name': 'Andrew'), ('points': 18)等。

name    points
Andrew  18
Kate    10
Jack    55
Andrew  31
Andrew  100
Jack    58
Andrew  34
Kate    22
Jack    5
Andrew  72

我想要做的是返回像Andrew: (5, 100)这样的键值对,其值为:

  1. 我在列表中遇到过多少次这个名字;
  2. 点数表中此名称的最大数量。

我对第一个任务没有问题,但找不到第二个任务的解决方案。这就是我试图做的事情:

name_counter = defaultdict(int)
max_points = defaultdict(int)
for dictionary in list_from_csv:
    name_counter[dictionary['name']] += 1 #every time I meet the name, I add +1 to the value
    max_points[dictionary['name']] = ??? 

我当时只想使用max(dictionary[points]),但是max应该从数字中选择,而不仅仅是一个。也许创建一个列表,但不知道如何。还有其他想法吗?

非常感谢任何帮助。

附:在我有这两个词后,我需要根据键来合并它们,但我希望它不那么难。

答案

你只需要在每次获得新价值时弄清楚如何处理max_points[name],对吧?

让我们假设,在每次迭代中,max_points[name]已经被正确设置为您目前所见的最高值。那么,你需要对新值做些什么呢?

简单:如果points大于你目前所见的最高值,它是新的最高值;如果不是,旧的最高值是新的最高值。

这正是max所做的。所以:

max_points[dictionary['name']] = max(max_points[dictionary['name']], points)

现在我们只需要验证假设是否正确。

  • 因为你正在使用defaultdict(int),它总是从0开始。如果你可以有负分数,那已经是错误的,但除此之外,它是正确的 - 你到目前为止看到的最高分,对于任何人来说,都是0。
  • 在每一步,如果它在上一步是正确的,那么在下一步之后它是正确的,因为这就是max所做的。
  • 因此,通过归纳,它最终是正确的。

作为旁注,不要一遍又一遍地重复dictionary['name'],它可能看起来更像这样:

for dictionary in list_from_csv:
    name = dictionary['name']
    name_counter[name] += 1
    max_points[name] = max(max_points[name], points)
另一答案

你可以使用itertools.groupby

import itertools
data = [{'name': 'Andrew', 'points': 18}, {'name': 'Kate', 'points': 10}, {'name': 'Jack', 'points': 55}, {'name': 'Andrew', 'points': 31}, {'name': 'Andrew', 'points': 100}, {'name': 'Jack', 'points': 58}, {'name': 'Andrew', 'points': 34}, {'name': 'Kate', 'points': 22}, {'name': 'Jack', 'points': 5}, {'name': 'Andrew', 'points': 72}]
grouped_data = [[a, list(b)] for a, b in itertools.groupby(sorted(data, key=lambda x:x['name']), key=lambda x:x['name'])]
final_data = [{a:(len(b), max(b, key=lambda x:x['points'])['points'])} for a, b in grouped_data]

输出:

[{'Andrew': (5, 100)}, {'Jack': (3, 58)}, {'Kate': (2, 22)}]
另一答案

为了完整起见,这里是第三方熊猫单线:

res = df.groupby('name')['points'].agg(['size', 'max'])

结果

print(res)

        size  max
name             
Andrew     5  100
Jack       3   58
Kate       2   22

建立

import pandas as pd
from io import StringIO

mystr = StringIO("""name    points
Andrew  18
Kate    10
Jack    55
Andrew  31
Andrew  100
Jack    58
Andrew  34
Kate    22
Jack    5
Andrew  72""")

df = pd.read_csv(mystr, delim_whitespace=True)
另一答案

这是一个解决方案,不使用除csv之外的任何额外导入。

我已将您的示例数据用作csv文件。我已经阅读了内容并创建了一个元组列表(名称,点数)

import csv
list_of_tuples = []

with open('f1.csv', newline='') as csv_file:
    dict_of_csv = csv.DictReader(csv_file)
    for item in dict_of_csv:
        list_of_tuples.append((item['name'], item['points']))

list_of_tuples看起来像这样

[('Andrew', '18'), ('Kate', '10'), ('Jack', '55'), ('Andrew', '31'), ('Andrew', '100'), ('Jack', '58'), ('Andrew', '34'), ('Kate', '22'), ('Jack', '5'), ('Andrew', '72')]

result_dict以{key:(tuple_0,tuple_1),}格式存储数据

{ name: (name_count, max_points),
  name1: (name_count1, max_points1),
  ...
}

字典中的值用它们的key标识,在这种情况下是name。 像dictionary['key']所以这里result_dict[name]元组中的数据可以作为普通列表访问,如元组[0]和元组[1] 所以在这里,它是result_dict[name][0]result_dict[name][1]

result_dict = {}
for dict_item in list_of_tuples:
    name = dict_item[0]
    points = int(dict_item[1])
    if name in result_dict:
        name_count = result_dict[name][0]
        max_points = result_dict[name][1]
        result_dict[name] = (name_count + 1, points if max_points < points else max_points)
    else:
        # the name isn't in the dictionary, so we add the "name: (name_count, max_points)" to it
        result_dict[name] = (1, points)

输出是:

{'Andrew': (5, 100), 'Kate': (2, 22), 'Jack': (3, 58)}

以上是关于使用相同的密钥从dict.values()获取最大值的主要内容,如果未能解决你的问题,请参考以下文章

dict.keys() 和 dict.values() 保证啥顺序? [复制]

dict.keys() 和 dict.values() 保证啥顺序? [复制]

Clojure - 使用最大值ArrayMap获取密钥

如何从 Firebase 中的第二个生成的密钥获取数据?

Python

尝试获取访问令牌时出现“请求无效,因为应用程序密钥与客户端令牌相同”错误