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

时间:2018-08-09 22:42:08

标签: python dictionary iteration

我有这个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应该从数字中选择,而不仅仅是一个。也许创建一个列表,但是不确定如何创建。还有其他想法吗?

不胜感激。

P.S。在我拥有这两个字典之后,我将需要根据密钥将它们合并,但是我希望它不会那么难。

4 个答案:

答案 0 :(得分:2)

每次获取新值时,您只需要弄清楚该怎么做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)

答案 1 :(得分:0)

您可以使用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)}]

答案 2 :(得分:0)

为完整起见,这是第三方熊猫一线客:

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)

答案 3 :(得分:0)

这是一个解决方案,不使用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']))

元组列表看起来像这样

[('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] 元组中的数据可以作为普通列表访问,例如tuple [0]和tuple [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)}