【问题标题】:How can I print the lines in STDIN in random order in Perl?如何在 Perl 中以随机顺序打印 STDIN 中的行?
【发布时间】:2008-11-13 09:35:23
【问题描述】:

我想做 sort(1) 的逆操作:在 Perl 中将 stdin 的每一行随机化为 stdout

【问题讨论】:

标签: perl unix sorting random


【解决方案1】:

我敢打赌,真正的 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 实现。它们是可互换的(除非您必须将打印与随机播放分开)。有关更多信息,请在您的 shell 上键入 perldoc -q rand。

【讨论】:

  • 你为什么使用$current?当数组已经知道这一点时,为什么还要手动维护数组的长度?
  • 因为我犯了错误 :-) 已修复。
  • 我想你想要 if (@lines == $bufsize)。照原样,您将每 514 行随机播放一次。
  • 我很好奇 - 为什么你认为“真正的 Perl 黑客”会撕毁它?它是可读的,它使用严格和警告,并且可以完成工作。
  • 好吧,我错了。我以为你的意思是那些会把它变成一行不可读的胡言乱语的人。 真正的 Perl 黑客了解生产代码和“Perl 高尔夫”之间的区别,除了修复一些错别字之外,您的代码不会有问题。 :-)
【解决方案2】:

这个 perl sn-p 可以解决问题:

#! /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__

【讨论】:

    【解决方案3】:
    use List::Util 'shuffle';
    print shuffle <>
    

    或者如果你担心最后几行缺少\n,

    chomp(my @lines = <>);
    print "$_\n" for shuffle @lines;
    

    【讨论】:

    • 这相当于 TheSnide 使用 shuffle 的解决方案(先吃掉所有东西,然后再洗牌)
    猜你喜欢
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    相关资源
    最近更新 更多