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