一切都在标题中。我想知道是否有人知道快速和合理的内存需求随机混合300万行文件的所有行的方式。我想用简单的vim命令是不可能的,所以任何使用Python的简单脚本都是如此。我通过使用随机数生成器尝试使用python,但没有设法找到一个简单的方法。
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 )
应该这样做。除非线路是巨大的(超过512个字符),否则300万行将适合大多数机器的内存。
在Python中只需几秒钟:
>>> import random
>>> lines = open('3mil.txt').readlines()
>>> random.shuffle(lines)
>>> open('3mil.txt', 'w').writelines(lines)
我刚刚在一个有4.3M行的文件上尝试了这个,最快的是Linux上的'shuf'命令。像这样使用它:
shuf huge_file.txt -o shuffled_lines_huge_file.txt
完成需要2-3秒。
在许多系统上,sort
shell命令使-R
随机化其输入。
这是另一个版本
在shell中,使用它。
python decorate.py | sort | python undecorate.py
decorate.朋友
import sys
import random
for line in sys.stdin:
sys.stdout.write( "{0}|{1}".format( random.random(), line ) )
UN decorate.朋友
import sys
for line in sys.stdin:
_, _, data= line.partition("|")
sys.stdout.write( line )
几乎没有记忆。
这与Kugelman先生的相同,但使用vim的内置python接口:
:py import vim, random as r; cb = vim.current.buffer ; l = cb[:] ; r.shuffle(l) ; cb[:] = l
如果您不想将所有内容加载到内存中并在那里进行排序,则必须在进行随机排序时将这些行存储在磁盘上。那将是非常缓慢的。
这是一个非常简单,愚蠢和缓慢的版本。请注意,这可能会占用大量磁盘空间,而且速度非常慢。我用300.000行运行它,需要几分钟。 300万行很可能需要一个小时。所以:在记忆中做。真。它不是那么大。
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数据库中,并从该数据库中随机抽取行。这可能会比这更快。
这是使用random.choice的另一种方式,这可能会提供一些渐进的记忆减轻,但与更糟糕的大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)
以下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()
执行它