Как я могу напечатать строки в STDIN в случайном порядке в Perl? - PullRequest
3 голосов
/ 13 ноября 2008

Я хочу сделать инверсию sort (1) : рандомизировать каждую строку от stdin до stdout в Perl.

Ответы [ 3 ]

10 голосов
/ 13 ноября 2008

Могу поспорить, что настоящие Perl-хакеры разорвут это на части, но, тем не менее, это так.

use strict;
use warnings;
use List::Util 'shuffle';

my @lines = ();
my $bufsize = 512;
while(<STDIN>) {
    push @lines, $_;
    if (@lines == $bufsize) {
        print shuffle(@lines);
        undef @lines;
    }
}
print shuffle(@lines);

Разница между этим и другим решением:

  • Не будет потреблять весь ввод и затем рандомизировать его (увеличение памяти), но будет рандомизировать каждые строки $ bufsize (не совсем случайные и медленные, как собака, по сравнению с другим вариантом).
  • Использует модуль, который возвращает новый список вместо редактирования Fisher - Yates на месте. Они являются взаимозаменяемыми (за исключением того, что вы должны отделить печать от случайного воспроизведения). Для получения дополнительной информации наберите perldoc -q rand в вашей оболочке.
5 голосов
/ 13 ноября 2008
use List::Util 'shuffle';
print shuffle <>

Или, если вам не хватает последних строк, \ n,

chomp(my @lines = <>);
print "$_\n" for shuffle @lines;
5 голосов
/ 13 ноября 2008

Этот фрагмент perl делает свое дело:

#! /usr/bin/perl
# randomize cat

# fisher_yates_shuffle code copied from Perl Cookbook 
# (By Tom Christiansen & Nathan Torkington; ISBN 1-56592-243-3)

use strict;

my @lines = <>;
fisher_yates_shuffle( \@lines );    # permutes @array in place
foreach my $line (@lines) {
    print $line;
}

# fisher_yates_shuffle( \@array ) : generate a random permutation
# of @array in place
sub fisher_yates_shuffle {
    my $array = shift;
    my $i;
    for ($i = @$array; --$i; ) {
        my $j = int rand ($i+1);
        next if $i == $j;
        @$array[$i,$j] = @$array[$j,$i];
    }
}

__END__
...