Перемешать записи списка текстовых файлов в одном файле - PullRequest
5 голосов
/ 27 июня 2011

У меня есть список текстовых файлов file1.txt, file2.txt, file3.txt .. filen.txt, которые мне нужно перемешать, создав один большой файл в результате *.

Требования
1. Записи данного файла должны быть обращены в обратном порядке перед перетасовкой
2. Записи данного файла должны хранить в обратном порядке в файле назначения
3. Я не знаю, сколько файлов мне нужно перетасовать, поэтому код должен быть как можно более универсальным (например, позволяя объявлять имена файлов в списке)
4. Файлы могут иметь разные размеры

Пример:

File1.txt
---------
File1Record1
File1Record2
File1Record3
File1Record4

File2.txt
---------
File2Record1
File2Record2


File3.txt
---------
File3Record1
File3Record2
File3Record3
File3Record4
File3Record5

вывод должен быть примерно таким:

ResultFile.txt
--------------
File3Record5   -|
File2Record2    |
File1Record4    |
File3Record4   -|
File2Record1    |
File1Record3    |-->File3 records are shuffled with the other records and 
File3Record3   -|   are correctly "reversed" and they kept the correct 
File1Record2    |   ordering
File3Record2   -|
File1Record1    |
File3Record1   -|

* Я не сумасшедший; Я должен импортировать эти файлы (сообщения в блоге), используя resultfile.txt в качестве ввода

EDIT:
результат может иметь любой вид, полностью или частично перетасованный, с равномерным чередованием, это не имеет значения. Важно то, что оба пункта 1. и 2. соблюдаются.

Ответы [ 8 ]

2 голосов
/ 27 июня 2011
filenames = [ 'filename0', ... , 'filenameN' ]
files = [ open(fn, 'r') for fn in filenames ]
lines = [ f.readlines() for f in files ]

output = open('output', 'w')

while len(lines) > 0:
    l = random.choice( lines )
    if len(l)==0: 
        lines.remove(l)
    else:
        output.write( l.pop() )

output.close()

Один кусочек может показаться здесь волшебным: строки, считанные из файлов, не нуждаются в обращении, потому что, когда мы записываем их в выходной файл, мы используем list.pop(), который берет элементы из конца списка (здесь содержимоефайла).

2 голосов
/ 27 июня 2011

Простое решение может состоять в том, чтобы создать список списков, а затем вытолкнуть строку из случайного списка, пока все они не будут исчерпаны:

>>> import random
>>> filerecords = [['File{0}Record{1}'.format(i, j) for j in range(5)] for i in range(5)]
>>> concatenation = []
>>> while any(filerecords):
...     selection = random.choice(filerecords)
...     if selection:
...         concatenation.append(selection.pop())
...     else:
...         filerecords.remove(selection)
... 
>>> concatenation
['File1Record4', 'File3Record4', 'File0Record4', 'File0Record3', 'File0Record2',
 'File4Record4', 'File0Record1', 'File3Record3', 'File4Record3', 'File0Record0',
 'File4Record2', 'File2Record4', 'File4Record1', 'File3Record2', 'File4Record0',
 'File2Record3', 'File1Record3', 'File2Record2', 'File2Record1', 'File3Record1',
 'File3Record0', 'File1Record2', 'File2Record0', 'File1Record1', 'File1Record0']
2 голосов
/ 27 июня 2011

Что по этому поводу:

>>> l = [["1a","1b","1c","1d"], ["2a","2b"], ["3a","3b","3c","3d","3e"]]
>>> while l:
...     x = random.choice(l)
...     print x.pop(-1) 
...     if not x:
...         l.remove(x)

1d
1c
2b
3e
2a
3d
1b
3c
3b
3a
1a

Вы можете оптимизировать его различными способами, но это общая идея. Это также работает, если вы не можете прочитать файлы сразу, но вам нужно перебирать их из-за ограничений памяти. В этом случае

  • читать строку из файла вместо всплывающего списка
  • проверка EOF вместо пустых списков
2 голосов
/ 27 июня 2011

вы можете попробовать следующее: на первом шаге вы zip() reversed() пунктов списка:

zipped = zip(reversed(lines1), reversed(lines2), reversed(lines3))

, затем вы можете объединить элементы в zip снова:

lst = []
for triple in zipped:
    lst.append(triple)

наконец вы должны удалить все None s, добавленные zip()

lst.remove(None)
0 голосов
/ 27 июня 2011

Возможная функция слияния доступна в стандартной библиотеке.Он предназначен для объединения отсортированных списков, чтобы создать отсортированные комбинированные списки;мусор, мусор, но у него есть желаемое свойство поддерживать порядок подсписков, несмотря ни на что.

def merge_files(output, *inputs):
    # all parameters are opened files with appropriate modes.
    from heapq import merge
    for line in heapq.merge(*(reversed(tuple(input)) for input in inputs)):
        output.write(line)
0 голосов
/ 27 июня 2011

Я не мастер дзен-питона, но вот мое мнение.

import random

#You have you read everything into a list from at least one of the files.
fin = open("filename1","r").readlines()
# tuple of all of the files.
fls = ( open("filename2","r"), 
       open("filename3","r"), )

for fl in fls: #iterate through tuple
   curr = 0
   clen = len(fin)
   for line in fl: #iterate through a file.
      # If we're at the end or 1 is randomly chosen, insert at current position.
      if curr > clen or round(random.random()):
         fin.insert(curr,line)
         clen = len(fin)
      curr +=1 #increment current index.

# when you're *done* reverse. It's easier.
fin.reverse()

К сожалению, с этим становится очевидным, что это взвешенное распределение.Это можно исправить, рассчитав длину каждого из файлов и умножив вызов на случайный на определенную вероятность, основываясь на этом.Я посмотрю, смогу ли я представить это позже.

0 голосов
/ 27 июня 2011
filelist = (
    'file1.txt',
    'file2.txt',
    'file3.txt',
)

all_records = []

max_records = 0
for f in filelist:
    fp = open(f, 'r')
    records = fp.readlines()
    if len(records) > max_records:
        max_records = len(records)
    records.reverse()
    all_records.append(records)
    fp.close()

all_records.reverse()

res_fp = open('result.txt', 'w')
for i in range(max_records):
    for records in all_records:
        try:
            res_fp.write(records[i])
        except IndexError:
            pass
    i += 1
res_fp.close()
0 голосов
/ 27 июня 2011

Я настоятельно рекомендую потратить некоторое время на чтение Советы по работе с генераторами для системных программистов (PDF). Это из презентации на PyCon 08 и посвящено обработке произвольно больших файлов журнала. Аспект разворота - интересная складка, но остальная часть презентации должна говорить непосредственно о вашей проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...