1

Let's say the text file is this:

1
2
3
4
5 
6
...

What I want is to randomely order the contents in groups of N lines, without shuffling the lines in each group, like this:

#In this case, N = 2.
5
6
1
2
7
8
...

My file isn't huge, it will be less than 50 lines for sure.

I've tried to do this using this code:

import random


with open("data.txt", "r") as file:
    lines = []
    groups = []
    for line in file:
        lines.append(line[:-1])
        if len(lines) > 3:
            groups.append(lines)


            lines = []

    random.shuffle(groups)


with open("data.txt", "w") as file:
    file.write("\n".join(groups))

But I get this error:

Traceback (most recent call last):
  File "C:/PYTHON/python/Data.py", line 19, in <module>
    file.write("\n".join(groups))
TypeError: sequence item 0: expected str instance, list found

Is there a simpler way of doing this?

1 Answers1

3

You tried to join a list of lists; flatten them first:

with open("data.txt", "w") as file:
    file.write("\n".join(['\n'.join(g) for g in groups]))

You could use any of the recommended methods of chunking to produce your groups. With a file object, all you need to do is zip() the file with itself:

with open("data.txt", "r") as file:
    groups = list(zip(file, file))

Note that this'll drop the last line if there are an odd number of lines in the file. This includes the newlines now, so join on '' rather than '\n'.

You could also join the two lines for each group together before shuffling:

with open("data.txt", "r") as file:
    groups = [a + b for a, b in zip(file, file)]

random.shuffle(groups)

with open("data.txt", "w") as file:
    file.write("".join(groups))
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks. Would there be any way to only open the file once? –  Oct 15 '17 at 11:55
  • @user1236969: sure: [Delete the contents of a file before writing to it (in Python)?](//stackoverflow.com/q/41915140); open in `'r+'` mode, read, rewind, truncate, then write. – Martijn Pieters Oct 15 '17 at 11:56