随机混合300万行文件

问题描述 投票:24回答:9

一切都在标题中。我想知道是否有人知道快速和合理的内存需求随机混合300万行文件的所有行的方式。我想用简单的vim命令是不可能的,所以任何使用Python的简单脚本都是如此。我通过使用随机数生成器尝试使用python,但没有设法找到一个简单的方法。

python random vim
9个回答
29
投票
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万行将适合大多数机器的内存。


41
投票

在Python中只需几秒钟:

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

15
投票

我刚刚在一个有4.3M行的文件上尝试了这个,最快的是Linux上的'shuf'命令。像这样使用它:

shuf huge_file.txt -o shuffled_lines_huge_file.txt

完成需要2-3秒。


3
投票

在许多系统上,sort shell命令使-R随机化其输入。


2
投票

这是另一个版本

在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 )

几乎没有记忆。


1
投票

这与Kugelman先生的相同,但使用vim的内置python接口:

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

1
投票

如果您不想将所有内容加载到内存中并在那里进行排序,则必须在进行随机排序时将这些行存储在磁盘上。那将是非常缓慢的。

这是一个非常简单,愚蠢和缓慢的版本。请注意,这可能会占用大量磁盘空间,而且速度非常慢。我用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数据库中,并从该数据库中随机抽取行。这可能会比这更快。


0
投票

这是使用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)

0
投票

以下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()执行它

© www.soinside.com 2019 - 2024. All rights reserved.