简体   繁体   English

在迭代时将键添加到int的defaultdict

[英]Adding keys to defaultdict of int while iterating

The script needs to read input from a text/csv file but as soon as I try and implement the functionality, everything breaks. 该脚本需要从text / csv文件读取输入,但是一旦我尝试实现该功能,一切都会中断。

Here is my code: 这是我的代码:

from collections import defaultdict
#from csv import reader

data = """Lions 3, Snakes 3
Tarantulas 1, FC Awesome 0
Lions 1, FC Awesome 1
Tarantulas 3, Snakes 1
Lions 4, Grouches 0"""

# with open('sample_input.csv') as data:
#     csv = reader(data)
#     list_csv = [line.rstrip('\n') for line in data]

data_list = data.splitlines()


def splitter(row):
    left_team, right_team = row.split(',')
    return {
        'left': left_team[:-2].strip(),
        'left_score': int(left_team[-2:].strip()),
        'right': right_team[:-2].strip(),
        'right_score': int(right_team[-2:].strip())
    }


data_dicts = [splitter(row) for row in data_list]


team_scores = defaultdict(int)
for game in data_dicts:
    if game['left_score'] == game['right_score']:
        team_scores[game['left']] += 1
        team_scores[game['right']] += 1
    elif game ['left_score'] > game['right_score']:
        team_scores[game['left']] += 3
    else:
        team_scores[game['right']] += 3
    print(team_scores)

teams_sorted = sorted(team_scores.items(), key=lambda team: team[1], reverse=True)


# for line in teams_sorted:
#     print(line)

Also, the expected output that I need to have is: 另外,我需要的预期输出是:

1. Tarantulas, 6 pts
2. Lions, 5 pts
3. FC Awesome, 1 pt
3. Snakes, 1 pt
4. Grouches, 0 pts

I just can't seem to figure out how to get to this step. 我只是似乎无法弄清楚如何执行此步骤。 I checked most parts of my code with print statements and it seems the dictionary is working correctly but it is not printing the last team and it's score (Grouches, 0 pts). 我用打印语句检查了代码的大部分内容,看来字典在正常工作,但没有打印最后一支队伍,而是得分(Grouches,0分)。

I am currently getting this output: 我目前正在获得此输出:

('Tarantulas', 6)
('Lions', 5)
('Snakes', 1)
('FC Awesome', 1)

Any help would be greatly appreciated! 任何帮助将不胜感激!

have you tried the CSV python lib? 您是否尝试过CSV python lib? Extracted from the doc ( https://docs.python.org/3/library/csv.html ): 从文档中提取( https://docs.python.org/3/library/csv.html ):

import csv
with open('data.csv', newline='') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
    for row in spamreader:
        print(', '.join(row))

Well done for getting this far. 能达到如此地步真是干的好。 You have managed to implement the logic, but have got stuck with a specific behaviour of defaultdict . 您已经成功实现了逻辑,但是陷入了defaultdict的特定行为。 There are 2 main points to note: 有两点要注意:

  1. If a key is not initialized with defaultdict , it won't be added to the dictionary. 如果没有使用defaultdict初始化键,则不会将其添加到字典中。 You can do this simply by adding 0 to a non-initialized key. 您只需在未初始化的键上加上0,即可完成此操作。
  2. For the specific formatting you require, you can use enumerate in a loop after sorting. 对于所需的特定格式,可以在排序后在循环中使用enumerate

Putting these together, amend your loop as below: 将它们放在一起,如下修改循环:

for game in data_dicts:
    if game['left_score'] == game['right_score']:
        team_scores[game['left']] += 1
        team_scores[game['right']] += 1
    elif game ['left_score'] > game['right_score']:
        team_scores[game['left']] += 3
        team_scores[game['right']] += 0
    else:
        team_scores[game['left']] += 0
        team_scores[game['right']] += 3

Then use enumerate in a loop. 然后在循环中使用enumerate You can use operator.itemgetter and f-strings (the latter in Python 3.6+) to make your logic cleaner: 您可以使用operator.itemgetter和f-strings(在Python 3.6+中使用后者)来使逻辑更简洁:

from operator import itemgetter

teams_sorted = sorted(team_scores.items(), key=itemgetter(1), reverse=True)

for idx, (team, score) in enumerate(teams_sorted, 1):
    print(f'{idx}. {team} {score} pts')

1. Tarantulas 6 pts
2. Lions 5 pts
3. Snakes 1 pts
4. FC Awesome 1 pts
5. Grouches 0 pts

To the code breaking on adding CSV. 给添加CSV的代码打断。 CSV reader does the split(',') for you. CSV阅读器为您执行split(',') So your left_team = row[0] and right_team = row[1] 因此,您的left_team = row[0] right_team = row[1]right_team = row[1]

So your code changes to something like 因此您的代码更改为

def spliter(row):
    left_team, right_team = row
    return {
        'left': left_team[:-2].strip(),
        'left_score': int(left_team[-2:].strip()),
        'right': right_team[:-2].strip(),
        'right_score': int(right_team[-2:].strip())
    }

with open('data.csv') as data_obj:
    reader = csv.reader(data_obj)
    data_dicts = [splitter(row) for row in reader]

You can go for plaintext reading if you want to manually split(',') . 如果要手动split(',')可以进行纯文本阅读。

with open('data.csv') as data_obj:
    data_list = [line.rstrip('\n') for line in data_obj.readlines()]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM