I'm creating a .txt file that has four soldiers on a team ranking each other in order of merit. Soldiers do not rank themselves.
I have the following code:
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
which produces the following output in a .txt 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
For each set of three lines (the sets of lines that start with the same soldier
), I want to add a randomized ranking that comes from possRanks
, where possRanks = [1, 2, 3]
. The problem is that I can't completely randomize it because then the rankings might repeat. For example, soldier1
might rank both soldier2
and soldier3
with a ranking of 1
, which I cannot have.
A correct example output would be the following:
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
Here, soldier1
ranks soldier2
with a value of 3
, soldier3
with a value of 1
, and soldier4
with a value of 2
.
Using your file as an example 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
We could read the file in N sized chunks using the itertools grouper recipe, shuffle possRanks
with random.shuffle
, then zip
each group with each shuffled rank. We can then open a new file to write to, such as 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")
Which will write a random shuffling of ranks to output.txt
every time you run the above:
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