Master-X
Форум | Новости | Статьи
Главная » Форум » Программинг, Скрипты, Софт, Сервисы » 
Тема: Быстрый shuffle скрипт
цитата
25/11/11 в 20:53
 FreeMann
всем привет.
очень нуждаюсь в быстром скрипте для рандомного shuffle записей внутри файла. записей более 20лямов.
такие варианты как:
1) cat list| sort -R >list- (под дебиан)
2) cat shuffle.pl
#!/usr/bin/perl -w
srand(time|$$);

@a = <>;

while ( @a ) {
$choice = splice(@a, rand @a, 1);
print $choice;
}
3) cat shuffle2.pl
#!/usr/bin/perl

while (<>) {
$mysort{$_}++;
}
foreach $str (keys %mysort) {
print $str
}
работают плохо и долго.

подскажите хороший скрипт.
цитата
26/11/11 в 03:32
 msth
не проще засунуть все записи в базу, сделать нужные индексы и рандомно выбирать из базы ?
цитата
26/11/11 в 11:41
 kodek
А что насчёт php shuffle?
Вот тут есть пример быстрой сортировки. Вкратце - там в массив грузятся не строки целиком, а только позиции начала строк (т.е. числа). Фактически, что-то вроде индексов, для текстового файла. На 500k строк он тестировал, не знаю как насчёт двух лямов будет, но попробовать можно - должно получиться.

Цитата:
If you use the first method, you can load about 50-60k lines for around 25megs of ram, if the lines are about 400-500 characters each. But using the second method (storing line positions), I was able to store 500-550k lines for around 25 megs of ram, which in turn is about 10x more better on ram usage. Alot better!
цитата
26/11/11 в 11:50
 ibiz
на думаю, что рнр будет быстрее...
как вариант попробовать разбить файл на мелкие части, через систему, по 1м строк:
split -l 1000000 /pathtofil/myfile
только не уверен, что будет большой выигрыш по времени

о каком времени и объемах идет речь хорошо бы уточнить trollface.png
цитата
26/11/11 в 16:53
 FreeMann
может пригодиться кому:

cat newlines.pl
#!/usr/bin/perl

use strict;
use warnings;

# Prepare
if(scalar @ARGV < 2) {
print STDERR "Usage: newlines.pl <infile> <outfile>\n";
exit 1;
}

my ($infile, $outfile) = @ARGV;

if(!-e $infile) {
print STDERR "Infile does not exist.\n";
exit 2;
}

if(!open(INFILE, '<', $infile)) {
print STDERR "Unable to open infile.\n";
exit 3;
}

# Load lines
my @lines = ();
my ($n, $f) = (0, 0);

while(<INFILE>) {
push(@lines, $_) and $n++;
}

close(INFILE);

# Shuffle
srand;
while(--$n) {
$f = int(rand($n + 1));
next if $n == $f;
@lines[$n, $f] = @lines[$f, $n];
}

# Output
open(OUTFILE, '>', $outfile);

foreach(@lines) {
print OUTFILE $_;
}

close(OUTFILE);

exit 0;

файл: 600мег, 26лямов строк

время работы скрипта составило полминуты !!!
процесс правда отожрал 2.5гига памяти.
цитата
26/11/11 в 22:36
 kodek
FreeMann писал:
может пригодиться кому...

Это чтобы сервер класть? icon_smile.gif
2.5 гига )
цитата
26/11/11 в 23:26
 Stek
А почему бы не загнать все это в базу и оттуда кроном генерить уже созданные рандомные куски ?
Скажем каждую минуту берем рандомно 10к записей и их используем.
цитата
27/11/11 в 12:24
 FreeMann
kodek писал:
Это чтобы сервер класть? icon_smile.gif
2.5 гига )


почему класть icon_smile.gif
сейчас дедики 16-96гигами оперативки не так и дорого стоят. так что если и отожреться процессом 2.5гига - то даже и заметно не будет.

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

спасибо всем.


Эта страница в полной версии