<p>我最关心的是代码的具体程度。例如,团队的名称被编码到特定的变量中,这些变量被单独处理。将玩家分成不同的团队是以特定数量的团队和可用玩家为前提的。等等。处理的每一位只对特定的预期数据起作用。你知道吗</p>
<p>第二个问题是如何在单个函数中完成所有操作。读取球员数据,把球员分到各个队,写下球队名单,这些都被塞进了一个综合功能中。你知道吗</p>
<p>那么,如何改进呢?首先,让我们更加模块化和通用化:</p>
<pre class="lang-py prettyprint-override"><code>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)
</code></pre>
<p>这个函数只关注一件事:读入播放器并返回一个列表。阅读后,我们可以将玩家分配到各个团队:</p>
<pre class="lang-py prettyprint-override"><code>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
</code></pre>
<p>请注意,从未提及特定的团队。这使得例程可以扩展到任意数量的团队或玩家。它使用一个常见的索引模列表大小技巧,在团队名称之间循环,依次分配每个团队名称。你知道吗</p>
<p>一旦团队被分配到名册上,就应该将其写入结果文件:</p>
<pre class="lang-py prettyprint-override"><code>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')
</code></pre>
<p>再次注意,代码不是特定于团队名称的。不管他们是龙还是独角兽。这些值是按常规方式处理的。你知道吗</p>
<p>最后,您需要一些命令和控制代码来将这些函数缝合在一起:</p>
<pre class="lang-py prettyprint-override"><code>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!')
</code></pre>
<p>虽然分配是随机的(按设计),但一次运行会发出一个文件<code>teams.txt</code>,如下所示。注意,我不担心有一个完整的18名球员。对18岁有效,但对6岁、9岁、12岁同样有效。。。事实上,它也适用于5岁、19岁和67岁。(不过,如果你打算在现实生活中使用它,那么很可能会看到许多奇数大小的玩家列表,你可能需要进一步改进这里使用的相当简单的公平算法。)</p>
<pre><code>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
</code></pre>