Добавление (неповторяющихся) случайных чисел в каждую строку .txt файла - PullRequest
1 голос
/ 30 апреля 2020

Я создаю .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

, который выдает следующий вывод в текстовом файле:

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 может ранжировать soldier2 и soldier3 с рейтингом 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 со значением 3, soldier3 со значением 1 и soldier4 со значением 2.

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

Вот еще один способ - просто использовать 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 для подсчета каждой итерации, и я создаю только новый случайный список из possRanks каждые x количества итераций, где x равно len of possRanks. Затем мы просто выталкиваем каждый элемент из списка, практически исчерпывая список при каждой итерации x, и создаем новый список после исчерпания.

1 голос
/ 30 апреля 2020

Используя ваш файл в качестве примера 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

Мы могли бы прочитать файл по N размерам, используя рецепт группировщика itertools , перемешать possRanks с random.shuffle, затем 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
...