在Python中读取CSV文件并分配给不同的列表

2024-05-13 10:52:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在关注一个在线Python项目,遇到了一些问题。我不觉得我的代码是非常'pythonic'和代码工作不正常。你知道吗

这个程序应该读取足球运动员的CSV文件。输出的意思是把队员分成三个不同的足球队。每个队都应该有相同数量的球员和相同数量的足球经验。18名球员中有9名有经验,这相当于6名队员中有3名有经验。我能做到,所以每支球队有六名球员,但我被绊倒的部分是经验。有些球队最终只有三支,但有些没有。以下是我迄今为止尝试过的:

import csv
import random

def assign_players():
    with open('soccer_players.csv') as csvfile:
        soccerplayers = csv.DictReader(csvfile)
        players = list(soccerplayers)

        target = open('teams.txt', 'w')

        raptors=[]
        dragons=[]
        sharks=[]

        for player in players:
            experienced_player = 0
            if len(raptors)<6:
                raptors.append(player)
                if player['Soccer Experience'] == 'YES':
                    experienced_player+=1
                    if experienced_player >3:
                        break

            elif len(dragons)<6:
                dragons.append(player)
                if player['Soccer Experience'] == 'YES':
                    experienced_player+=1
                    if experienced_player >3:
                        break

            else:
                sharks.append(player)
                # if player['Soccer Experience'] == 'YES':
                #     experienced_player+=1
                #     if experienced_player >3:
                #         break

        target.write("Raptors")
        target.write("\n")
        for raptor in raptors:
            target.write(str(raptor["Name"])+ ', '),
            target.write(str(raptor["Soccer Experience"])+ ', '), " ",
            target.write(str(raptor["Guardian Name(s)"])+ ' '), " ",
            target.write("\n")

        target.write("\n")

        target.write("Dragons")
        target.write("\n")
        for dragon in dragons:
            target.write(str(dragon["Name"]) + ', '),
            target.write(str(dragon["Soccer Experience"]) + ', '), " ",
            target.write(str(dragon["Guardian Name(s)"]) + ' '), " ",
            target.write("\n")

        target.write("\n")

        target.write("Sharks")
        target.write("\n")
        for shark in sharks:
            target.write(str(shark["Name"]) + ', '),
            target.write(str(shark["Soccer Experience"]) + ', '), " ",
            target.write(str(shark["Guardian Name(s)"]) + ' '), " ",
            target.write("\n")

if __name__ == "__main__":
     assign_players()

这是一个足球比赛的例子_玩家.csv文件已格式化

Name,Height (inches),Soccer Experience,Guardian Name(s)
Joe Smith,42,YES,Jim and Jan Smith

Tags: csvnametargetforif经验writeexperience
2条回答

我最关心的是代码的具体程度。例如,团队的名称被编码到特定的变量中,这些变量被单独处理。将玩家分成不同的团队是以特定数量的团队和可用玩家为前提的。等等。处理的每一位只对特定的预期数据起作用。你知道吗

第二个问题是如何在单个函数中完成所有操作。读取球员数据,把球员分到各个队,写下球队名单,这些都被塞进了一个综合功能中。你知道吗

那么,如何改进呢?首先,让我们更加模块化和通用化:

def read_players(filepath):
    """
    Read a list of players (each one represented by a 
    dictionary), and return the list.
    """
    with open(filepath) as csvfile:
        soccerplayers = csv.DictReader(csvfile)
        return list(soccerplayers)

这个函数只关注一件事:读入播放器并返回一个列表。阅读后,我们可以将玩家分配到各个团队:

def assign_teams(players, teams):
    """
    Given a list of players and a list of teams, randomly assign
    players to teams but in a fair way that balances experienced 
    players as evenly as possible across teams. Returns a dictionary 
    mapping team name -> list of players on the team.
    """
    # shuffle order of teams and players so there's no hint of 
    # favoritism
    random.shuffle(teams)
    random.shuffle(players)

    # partition player list into experienced and inexperienced players
    experienced   = [ p for p in players if p['Soccer Experience'] == 'YES']
    inexperienced = [ p for p in players if p['Soccer Experience'] == 'NO']

    # create a roster
    n_teams = len(teams)
    roster = {team_name: [] for team_name in teams}

    # pick the experienced players (round-robin)
    for i, player in enumerate(experienced):
        team = teams[i % n_teams]
        roster[team].append(player)

    # add inexperienced players (round-robin)
    for i, player in enumerate(inexperienced):
        team = teams[i % n_teams]
        roster[team].append(player)

    return roster

请注意,从未提及特定的团队。这使得例程可以扩展到任意数量的团队或玩家。它使用一个常见的索引模列表大小技巧,在团队名称之间循环,依次分配每个团队名称。你知道吗

一旦团队被分配到名册上,就应该将其写入结果文件:

def write_roster(roster, filepath):
    """
    Write a roster dictionary to the given filepath.
    """
    fields = ["Name", "Soccer Experience", "Guardian Name(s)"]
    with open(filepath, 'w') as f:
        for team in roster.keys():
            f.write(team + '\n')
            for player in roster[team]:
                # select just the desired fields for output
                row = [player[f] for f in fields]
                # construct and write out a formatted record
                formatted_row = ', '.join(row) + '\n'
                f.write(formatted_row)
            # separate teams with a little more white space
            f.write('\n')

再次注意,代码不是特定于团队名称的。不管他们是龙还是独角兽。这些值是按常规方式处理的。你知道吗

最后,您需要一些命令和控制代码来将这些函数缝合在一起:

if __name__ == "__main__":
    players = read_players('soccer_players.csv')
    teams = ['Raptors', 'Dragons', 'Sharks']
    roster = assign_teams(players, teams)
    write_roster(roster, 'teams.txt')
    print('done!')

虽然分配是随机的(按设计),但一次运行会发出一个文件teams.txt,如下所示。注意,我不担心有一个完整的18名球员。对18岁有效,但对6岁、9岁、12岁同样有效。。。事实上,它也适用于5岁、19岁和67岁。(不过,如果你打算在现实生活中使用它,那么很可能会看到许多奇数大小的玩家列表,你可能需要进一步改进这里使用的相当简单的公平算法。)

Dragons
Todd Jacobs, YES, Robert and Virginia Jacobs
Doug Jones, NO, Mary and Perry Jones
David Nork, NO, Dan and Stacy Nork

Raptors
Joe Smith, YES, Jim and Jan Smith
Will Smith, NO, Bill and Nancy Smith
Mark Jackson, NO, Jack and Frank Jackson

Sharks
Bill Smith, YES, Jim and Jan Smith
Andy Able, NO, Noah Able
Paul Pork, NO, Paul and Paulette Pork

这里有一个解决方案,适用于任何数量的球员和球队。它随机洗牌玩家列表,按经验排序,然后循环分配玩家到可用的团队:

#!python3
import csv
import random
import itertools
import operator
from collections import namedtuple

Team = namedtuple('Team','name players')

teams = Team('Raptors',[]), Team('Dragons',[]), Team('Sharks',[])

with open('soccer_players.csv', newline='') as csvfile:
    players = list(csv.DictReader(csvfile))

random.shuffle(players)
players.sort(key=operator.itemgetter('Soccer Experience'))

iteam = itertools.cycle(teams)
for player in players:
        next(iteam).players.append(player)

with open('teams.txt', 'w') as target:
    for team in teams:
        target.write(team.name + '\n')
        for player in team.players:
            target.write('{Name}, {Soccer Experience}, {Guardian Name(s)}\n'.format(**player))
        target.write('\n')

输入文件(不是很原始,但没有提供):

Name,Height (inches),Soccer Experience,Guardian Name(s)
A,40,YES,aaa
B,40,YES,bbb
C,40,YES,ccc
D,40,YES,ddd
E,40,YES,eee
F,40,YES,fff
G,40,YES,ggg
H,40,YES,hhh
I,40,YES,iii
J,40,NO,jjj
K,40,NO,kkk
L,40,NO,lll
M,40,NO,mmm
N,40,NO,nnn
O,40,NO,ooo
P,40,NO,ppp
Q,40,NO,qqq
R,40,NO,rrr

输出文件:

Raptors
M, NO, mmm
O, NO, ooo
J, NO, jjj
A, YES, aaa
H, YES, hhh
B, YES, bbb

Dragons
L, NO, lll
N, NO, nnn
P, NO, ppp
C, YES, ccc
I, YES, iii
E, YES, eee

Sharks
R, NO, rrr
Q, NO, qqq
K, NO, kkk
G, YES, ggg
D, YES, ddd
F, YES, fff

相关问题 更多 >