向 .txt 文件的每一行添加(非重复)随机数

Adding (non-repeating) Random Numbers to Each Line of .txt File

我正在创建一个 .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排名soldier2,值为3soldier3排名为1soldier4排名为2.

的值

以您的文件为例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, shuffle possRanks with random.shuffle, then zip 每个组和每个打乱的排名来读取 N 个大小的块中的文件。然后我们可以打开一个新文件来写入,例如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

这是另一种使用 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 来计算每次迭代,并且只创建 每 x 次迭代的新随机列表 possRanks,其中 x 等于 len of possRanks。 然后我们只是从列表中弹出每个项目,基本上每 x 次迭代耗尽列表,并在耗尽后创建一个新列表。