2017-02-25 158 views
0

我正在关注在线Python项目并遇到一些问题。我不觉得我的代码非常“pythonic”,代码工作不正常。在Python中读取CSV文件并分配到不同的列表

该程序应该读取足球运动员的CSV文件。输出是为了将玩家分成三个不同的足球队。每支球队应该拥有与足球经验相同数量的球员和相同的金额。在18名球员中,有9名经验丰富,因此相当于六名球队成员,六名球员中有三名经验丰富。我能得到它,所以每个球队都有六名球员,但我被绊倒的部分是经验部分。一些球队以三个结局,但一些不是。以下是我试过到目前为止:

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() 

这是的soccer_players.csv文件是如何格式化

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

请明确指定您的问题。把一两句话简单化,少说明,多数据例子是很好的。 – j0e1in

回答

0

最关心的问题我不得不与代码是多么特殊。例如,团队的名称被编码成特定的变量,这些变量是单独处理的。球员分给球队的假设是假定具体的球队和球员数量。等等处理的每一点都只适用于特定的预期数据。第二个问题是如何在单个功能中完成所有的事情。读取玩家数据,将玩家分配给团队,写出团队名单 - 将其全部塞进一个综合功能中。

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

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 
+0

乔纳森 - 感谢您花时间处理此问题,并逐步详细解释所有内容。在我目前使用Python的经验中,其中一些是我的头脑 - 但我可以告诉你,代码完美工作。我会回过头去尝试研究一些我还没完全理解的东西。再次感谢你,这对我来说是非常宝贵的。 –

1

样本下面是为任意数量的球员和球队工作的解决方案。它随机洗牌的球员名单,由经验排序,然后循环分配玩家可用的球队:

#!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 
+0

我喜欢你的单层分配策略(排序然后循环)。我也想达到'itertools',但决定避免它更简单(尽管稍长一点和较低级别)的代码。 –

+0

马克这是伟大的 - 感谢您的帮助。在你和乔纳森的帮助之间,我只能说我真的很欣赏你们做的事情!谢谢 –

+0

@JohnRogerson不客气。请提出有帮助的答案,并选择一个作为接受的答案(如果适用)以及:) –