我有一堆文件,而且文件有5行的标题。在文件的其余部分,一对行形成一个条目。我需要从这些文件中随机选择条目。 如何选择随机文件和随机条目(一对行,不包括标题)?
答案 0 :(得分:6)
您可能会发现perlfaq5有用。
答案 1 :(得分:6)
如果文件足够小,请将行对读入内存,然后从该数据结构中随机选择。如果文件太大,Eugene Y会提供正确的答案:使用reservoir sampling。
这是算法的直观解释。
Process the file line by line.
pick = line, with probability 1/N, where N = line number
换句话说,在第1行,我们将以1/1
概率选择第1行。在第2行,我们将更改选择到第2行,概率为1/2
。在第3行,我们将选择更改为第3行,概率为1/3
。等
为了直观证明,想象一下有3行的文件:
1 Pick line 1.
/ \
.5 .5
/ \
2 1 Switch to line 2?
/ \ / \
.67 .33 .33 .67
/ \ / \
2 3 1 Switch to line 3?
每个结果的可能性:
Line 1: .5 * .67 = 1/3
Line 2: .5 * .67 = 1/3
Line 3: .5 * .33 * 2 = 1/3
从那里开始,其余的就是感应。例如,假设文件有4行。我们已经说服自己,从第3行开始,到目前为止,每一行(1,2,3)都有平等的机会成为我们的当前选择。当我们前进到第4行时,它将有1/4
被挑选的机会 - 正是它应该是什么,从而将前3行的概率减少恰当的数量(1/3 * 3/4 = 1/4
)。
这是适合您问题的Perl FAQ answer。
use strict;
use warnings;
# Ignore 5 lines.
<> for 1 .. 5;
# Use reservoir sampling to select pairs from remaining lines.
my (@picks, $n);
until (eof){
my @lines;
$lines[$_] = <> for 0 .. 1;
$n ++;
@picks = @lines if rand($n) < 1;
}
print @picks;
答案 2 :(得分:3)
sed "1,5d" < FILENAME | sort -R | head -2
答案 3 :(得分:3)
像这样调用getRandomItems(file('myHuge.log'), 5, 2)
- 将返回2行的列表
from random import randrange
def getRandomItems(f, skipFirst=0, numItems=1):
for _ in xrange(skipFirst):
f.next()
n = 0; r = []
while True:
try:
nxt = [f.next() for _ in range(numItems)]
except StopIteration: break
n += 1
if not randrange(n):
r = nxt
return r
如果无法从f获取第一个可通过的项目,则返回空列表。代码的唯一要求是参数f
是一个迭代器(支持next()
方法)。因此,我们可以传递与文件不同的内容,比如说我们想要查看分发:
>>> s={}
>>> for i in xrange(5000):
... r = getRandomItems(iter(xrange(50)))[0]
... s[r] = 1 + s.get(r,0)
...
>>> for i in s:
... print i, '*' * s[i]
...
0 ***********************************************************************************************
1 **************************************************************************************************************
2 ******************************************************************************************************
3 ***************************************************************************
4 *************************************************************************************************************************
5 ********************************************************************************
6 **********************************************************************************************
7 ***************************************************************************************
8 ********************************************************************************************
9 ********************************************************************************************
10 ***********************************************************************************************
11 ************************************************************************************************
12 *******************************************************************************************************************
13 *************************************************************************************************************
14 ***************************************************************************************************************
15 *****************************************************************************************************
16 ********************************************************************************************************
17 ****************************************************************************************************
18 ************************************************************************************************
19 **********************************************************************************
20 ******************************************************************************************
21 ********************************************************************************************************
22 ******************************************************************************************************
23 **********************************************************************************************************
24 *******************************************************************************************************
25 ******************************************************************************************
26 ***************************************************************************************************************
27 ***********************************************************************************************************
28 *****************************************************************************************************
29 ****************************************************************************************************************
30 ********************************************************************************************************
31 ********************************************************************************************
32 ****************************************************************************************************
33 **********************************************************************************************
34 ****************************************************************************************************
35 **************************************************************************************************
36 *********************************************************************************************
37 ***************************************************************************************
38 *******************************************************************************************************
39 **********************************************************************************************************
40 ******************************************************************************************************
41 ********************************************************************************************************
42 ************************************************************************************
43 ****************************************************************************************************************************
44 ****************************************************************************************************************************
45 ***********************************************************************************************
46 *****************************************************************************************************
47 ***************************************************************************************
48 ***********************************************************************************************************
49 ****************************************************************************************************************
答案 4 :(得分:1)
答案是Python。假设您可以将整个文件读入内存。
#using python 2.6
import sys
import os
import itertools
import random
def main(directory, num_files=5, num_entries=5):
file_paths = os.listdir(directory)
# get a random sampling of the available paths
chosen_paths = random.sample(file_paths, num_files)
for path in chosen_paths:
chosen_entries = get_random_entries(path, num_entries)
for entry in chosen_entries:
# do something with your chosen entries
print entry
def get_random_entries(file_path, num_entries):
with open(file_path, 'r') as file:
# read the lines and slice off the headers
lines = file.readlines()[5:]
# group the lines into pairs (i.e. entries)
entries = list(itertools.izip_longest(*[iter(lines)]*2))
# return a random sampling of entries
return random.sample(entries, num_entries)
if __name__ == '__main__':
#use optparse here to do fancy things with the command line args
main(sys.argv[1:])
答案 5 :(得分:0)
另一个Python选项;将所有文件的内容读入内存:
import random
import fileinput
def openhook(filename, mode):
f = open(filename, mode)
headers = [f.readline() for _ in range(5)]
return f
num_entries = 3
lines = list(fileinput.input(openhook=openhook))
print random.sample(lines, num_entries)
答案 6 :(得分:0)
另外两种方法: 1-由生成器(可能仍需要大量内存): http://www.usrsb.in/Picking-Random-Items--Take-Two--Hacking-Python-s-Generators-.html
2-聪明的寻求(实际上最好的方法): http://www.regexprn.com/2008/11/read-random-line-in-large-file-in.html
我在这里复制了聪明的Jonathan Kupferman的代码:
#!/usr/bin/python
import os,random
filename="averylargefile"
file = open(filename,'r')
#Get the total file size
file_size = os.stat(filename)[6]
while 1:
#Seek to a place in the file which is a random distance away
#Mod by file size so that it wraps around to the beginning
file.seek((file.tell()+random.randint(0,file_size-1))%file_size)
#dont use the first readline since it may fall in the middle of a line
file.readline()
#this will return the next (complete) line from the file
line = file.readline()
#here is your random line in the file
print line