【问题标题】:Adding (non-repeating) Random Numbers to Each Line of .txt File向 .txt 文件的每一行添加(非重复)随机数
【发布时间】:2020-04-30 03:23:56
【问题描述】:

我正在创建一个 .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

在这里,soldier1soldier2 的值 3soldier3 的值 1soldier4 的值的 2 排名。

【问题讨论】:

标签: python random text itertools edge-list


【解决方案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 大小的块读取文件,使用random.shuffle 随机播放possRanks,然后zip 每个组使用每个随机排序。然后我们可以打开一个要写入的新文件,例如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

【讨论】:

    【解决方案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 迭代都会耗尽列表,并在耗尽后创建一个新列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多