Подтвердить что ты не робот

Случайно смешивать строки из файла с 3 миллионами строк

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

4b9b3361

Ответ 1

import random
with open('the_file','r') as source:
    data = [ (random.random(), line) for line in source ]
data.sort()
with open('another_file','w') as target:
    for _, line in data:
        target.write( line )

Это должно сделать это. 3 миллиона строк будут вписываться в большую часть памяти компьютера, если только линии не являются ОГРОМНЫМИ (более 512 символов).

Ответ 2

В Python занимает всего несколько секунд:

>>> import random
>>> lines = open('3mil.txt').readlines()
>>> random.shuffle(lines)
>>> open('3mil.txt', 'w').writelines(lines)

Ответ 3

Я просто попробовал это в файле с 4.3M строк, и самая быстрая вещь была командой "shuf" в Linux. Используйте его так:

shuf huge_file.txt -o shuffled_lines_huge_file.txt

Потребовалось 2-3 секунды.

Ответ 4

Во многих системах команда оболочки sort принимает -R, чтобы рандомизировать ее вход.

Ответ 5

Здесь другая версия

В оболочке используйте это.

python decorate.py | sort | python undecorate.py

decorate.py

import sys
import random
for line in sys.stdin:
    sys.stdout.write( "{0}|{1}".format( random.random(), line ) )

undecorate.py

import sys
for line in sys.stdin:
    _, _, data= line.partition("|")
    sys.stdout.write( line )

Использует почти не память.

Ответ 6

Это то же самое, что и г-н Кугельман, но используя встроенный интерфейс python vim:

:py import vim, random as r; cb = vim.current.buffer ; l = cb[:] ; r.shuffle(l) ; cb[:] = l

Ответ 7

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

Вот очень простая, глупая и медленная версия. Обратите внимание, что это может занять удивительное количество дискового пространства, и оно будет очень медленным. Я запускал его с 300 000 строк, и это занимает несколько минут. 3 миллиона линий могут очень хорошо принять час. Итак: сделайте это в памяти. В самом деле. Это не так уж и важно.

import os
import tempfile
import shutil
import random
tempdir = tempfile.mkdtemp()
print tempdir

files = []
# Split the lines:
with open('/tmp/sorted.txt', 'rt') as infile:
    counter = 0    
    for line in infile:
        outfilename = os.path.join(tempdir, '%09i.txt' % counter)
        with open(outfilename, 'wt') as outfile:
            outfile.write(line)
        counter += 1
        files.append(outfilename)

with open('/tmp/random.txt', 'wt') as outfile:
    while files:
        index = random.randint(0, len(files) - 1)
        filename = files.pop(index)
        outfile.write(open(filename, 'rt').read())

shutil.rmtree(tempdir)

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

Ответ 8

Вот еще один способ использования random.choice, который также может обеспечить некоторое постепенное освобождение памяти, но с худшим Big-O :)

from random import choice

with open('data.txt', 'r') as r:
    lines = r.readlines()

with open('shuffled_data.txt', 'w') as w:
    while lines:
        l = choice(lines)
        lines.remove(l)
        w.write(l)

Ответ 9

Следующий Vimscript может использоваться для замены строк:

function! Random()                                                       
  let nswaps = 100                                                       
  let firstline = 1                                                     
  let lastline = 10                                                      
  let i = 0                                                              
  while i <= nswaps                                                      
    exe "let line = system('shuf -i ".firstline."-".lastline." -n 1')[:-2]"
    exe line.'d'                                                         
    exe "let line = system('shuf -i ".firstline."-".lastline." -n 1')[:-2]"
    exe "normal! " . line . 'Gp'                                         
    let i += 1                                                           
  endwhile                                                               
endfunction

Выберите функцию в визуальном режиме и введите :@" затем выполните ее с помощью :call Random()

Ответ 10

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

import sys
lines= list(set(open(sys.argv[1]).readlines()))
print(' '.join(lines))

в оболочке

python shuffler.py nameoffilestobeshuffled.txt > shuffled.txt