3

私はsort(1)の逆を行いたい: Perlでstdinのすべての行をstdoutにランダム化します。

4

3 に答える 3

10

本当の 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 と入力してください。
于 2008-11-13T09:39:52.797 に答える
6

この 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__
于 2008-11-13T09:36:58.760 に答える
5
use List::Util 'shuffle';
print shuffle <>

または、最後の行に \n がないことを心配している場合は、

chomp(my @lines = <>);
print "$_\n" for shuffle @lines;
于 2008-11-13T18:17:11.590 に答える