1

我正在创建一个 .txt 文件,该文件中有四名士兵在一个团队中按功绩排序。士兵不给自己排名。

我有以下代码:

import itertools

# create a list of 4 soldiers
numSoldiers=4
soldiers = []
for i in range(1,numSoldiers+1):
    soldiers.append('soldier'+str(i))

# create list of all permutations of 2 soldiers
perms = list(itertools.permutations(soldiers, 2))

# list of possible rankings (soldier does not rank himself/herself)
possRanks = list(range(1,len(soldiers)))

# create the edgelist .txt file with randomized rankings
open('peerRankingsEdgelist.txt', 'w').close() #delete contents of .txt file at the start

file = open('peerRankingsEdgelist.txt', 'w')

for i in perms:
    file.write(i[0] + ', ' + i[1] + '\n')

file.close() #close file

在 .txt 文件中生成以下输出:

soldier1, soldier2
soldier1, soldier3
soldier1, soldier4
soldier2, soldier1
soldier2, soldier3
soldier2, soldier4
soldier3, soldier1
soldier3, soldier2
soldier3, soldier4
soldier4, soldier1
soldier4, soldier2
soldier4, soldier3

对于每组三行(以相同开头的行组soldier),我想添加一个随机排名,该排名来自possRanks,其中possRanks = [1, 2, 3]。问题是我不能完全随机化它,因为那样排名可能会重复。例如,soldier1可能同时排名soldier2soldier3排名为1,这是我无法拥有的。

正确的示例输出如下:

soldier1, soldier2, 3
soldier1, soldier3, 1
soldier1, soldier4, 2
soldier2, soldier1, 1
soldier2, soldier3, 2
soldier2, soldier4, 3
soldier3, soldier1, 2
soldier3, soldier2, 1
soldier3, soldier4, 3
soldier4, soldier1, 1
soldier4, soldier2, 2
soldier4, soldier3, 3

在这里,用 的值、用 的值和用 的值进行soldier1排名。soldier23soldier31soldier42

4

2 回答 2

1

这是另一种使用enum可能更容易解析的方法;

import itertools
import random

# create a list of 4 soldiers
numSoldiers=4
soldiers = []
for i in range(1,numSoldiers+1):
    soldiers.append('soldier'+str(i))

# create list of all permutations of 2 soldiers
perms = list(itertools.permutations(soldiers, 2))

# list of possible rankings (soldier does not rank himself/herself)
possRanks = list(range(1,len(soldiers)))

# create the edgelist .txt file with randomized rankings
open('peerRankingsEdgelist.txt', 'w').close() #delete contents of .txt file at the start

file = open('peerRankingsEdgelist.txt', 'w')

for num, i in enumerate(perms):
    if num % len(possRanks) == 0:
        shuffled_ranks = possRanks.copy()
        random.shuffle(shuffled_ranks)

    random_rank = str(shuffled_ranks.pop())

    line = (i[0]) + ', ' + i[1] + ',' + random_rank + '\n'


    file.write(line)

file.close() #close file

所以我唯一改变的部分是这里:

for num, i in enumerate(perms):
        if num % len(possRanks) == 0:
            shuffled_ranks = possRanks.copy()
            random.shuffle(shuffled_ranks)

        random_rank = str(shuffled_ranks.pop())

        line = (i[0]) + ', ' + i[1] + ',' + random_rank + '\n'

基本上我enumerate用来计算每次迭代,并且只创建每个迭代次数的新随机列表possRanksx其中x等于len of possRanks. 然后我们只是从列表中弹出每个项目,基本上每次x迭代都会耗尽列表,并在耗尽后创建一个新列表。

于 2020-04-30T05:21:30.290 回答
1

以您的文件为例data.txt

soldier1, soldier2
soldier1, soldier3
soldier1, soldier4
soldier2, soldier1
soldier2, soldier3
soldier2, soldier4
soldier3, soldier1
soldier3, soldier2
soldier3, soldier4
soldier4, soldier1
soldier4, soldier2
soldier4, soldier3

我们可以使用itertools grouper recipe以 N 大小的块读取文件,使用shuffle possRanksrandom.shuffle然后zip每个组使用每个 shuffle 的等级。然后我们可以打开一个新文件来写入,例如output.txt.

from random import shuffle
from itertools import zip_longest

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

possRanks = [1, 2, 3]

with open("data.txt") as f, open("output.txt", mode="w") as o:
    for line in grouper(map(str.strip, f), len(possRanks), ''):
        shuffle(possRanks)
        for group, rank in zip(line, possRanks):
            o.write(f"{group}, {rank}\n")

output.txt每次运行上述命令时,都会随机排列等级:

soldier1, soldier2, 2
soldier1, soldier3, 1
soldier1, soldier4, 3
soldier2, soldier1, 1
soldier2, soldier3, 3
soldier2, soldier4, 2
soldier3, soldier1, 2
soldier3, soldier2, 3
soldier3, soldier4, 1
soldier4, soldier1, 3
soldier4, soldier2, 1
soldier4, soldier3, 2
于 2020-04-30T03:47:42.597 回答