【问题标题】:Making a perl array unique使 perl 数组唯一
【发布时间】:2012-08-03 18:46:08
【问题描述】:

我目前在捕获反引号 shell 命令的输出时遇到了一个非常简单的问题。我很抱歉这个问题很简单。

我有一些排序数组 (@valid_runs),我知道包含连续的重复元素。我想使用反引号将此数组回显到 uniq。我想在一个数组中捕获 STDOUT。我尝试这样做。

@unique_valids = `echo '@valid_runs' | uniq`;
print @unique_valids;

这个打印语句没有产生任何结果。就此而言,这也不是。

@unique_valids = `echo '@valid_runs'`;
print @unique_valids;

我知道如何使用 uniq 和 echo。这对我来说似乎很奇怪。我认为这与 perl 数组有关,而不是正确使用这些命令。我在其他地方搜索了一下,所以请不要仅仅因为解决方案看起来微不足道而对我投反对票。再次感谢您的宝贵时间。

解决方案注意事项: 就处理 uniq 问题而言,TLP 的解决方案是最直接的。我相当灵活,因为所有回复都建议不要针对这个问题进行系统调用。如果 Perl 的 uniq 函数与 Unix 的 uniq 函数相同,那么数组应该保持排序状态。

如果您不关心排序结果,John Corbett 的解决方案效果很好。

【问题讨论】:

  • 一个潜在问题:@valid_runs 的元素是否以换行符结尾?否则echo 将只产生一行输出作为uniq 的输入
  • 您确定@valid_runs 不为空吗?这为我打印了一些东西:@x=(3,2,1);@y = `echo '@x'`;print @y;
  • @user5402 我确定@valid 运行不为空。我确信每个条目在字符串的末尾都有一个换行符。你的例子有效。这很好;向我表明我并没有提出任何太疯狂的建议。这是@valid_runs 的sn-p:/raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36415 /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36415 /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36416 /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36416
  • 有关您可能希望在 Perl 中处理数组的各种事情的讨论,例如获取两个数组之间的差异,请参阅 Perl 常见问题解答:perldoc.perl.org/perlfaq4.html#Data:-Arrays

标签: arrays perl unix uniq


【解决方案1】:

将系统调用用于可以通过 perl 代码轻松完成的事情并不是一个好主意。 List::MoreUtils 模块有一个 uniq 函数,可以满足您的要求:

use List::MoreUtils qw(uniq);

my @unique = uniq @runs;

模块内部的子程序本身非常简单,不过,就像 theglauber 的回答一样:

sub uniq (@) {
    my %seen = ();
    grep { not $seen{$_}++ } @_;
}

【讨论】:

  • 是的,对于当前的解决方案,我只是在 Perl 中实现一些东西。进行不必要的系统调用是不好的。我只是懒惰,因为我已经知道 uniq。感谢您的宝贵时间。
【解决方案2】:

您应该将数组存储到散列中,因为散列键始终是唯一的。你可以这样做:

my %temp_hash = map { $_ => 1 } @valid_runs;
my @unique_valids = keys %temp_hash;

无论如何,这就是 perl 的做法。这里没有必要使用背部抽动(我尽量避免这些)。

【讨论】:

  • 这不会保留数组的顺序。
  • 他没说需要保存
  • 在这种情况下它不是必需的,但是我确实希望能够做一些简单的事情,比如将数组放入 shell 命令中。 @JohnCorbett 感谢您的解决方案。它实现了需要做的事情,但我仍然想知道如何做我建议的事情。
【解决方案3】:

在 perl 中很容易做到这一点。下面是一种对数组进行重复数据删除的相当晦涩但有趣的方法:

@dedup = grep !$seen{$_}++ @orig_array;

通过查看 perl 函数 grep 的文档了解这是做什么的。

如果您必须使用uniq,您可能需要将每个数组元素放在单独的行中。

join("\n", @your_array)

应该能做到这一点。

【讨论】:

    【解决方案4】:
    #!/usr/bin/perl
    use warnings;
    
    @a = (1, 2, 3, 3, 4, 4, 5);
    
    $cmd = "/usr/bin/uniq <<EOF\n";
    $cmd .= $_."\n" foreach (@a);
    $cmd .= "EOF\n";
    
    $result = `$cmd`;
    print "Cmd: $cmd\n";
    print "Result is $result";
    
    @u = split /\n/,$result;
    print "After ",join " ",@u,"\n";
    

    这可以满足您的要求,但 theglauber 的答案仍然比 Perl 更好。

    【讨论】:

      猜你喜欢
      • 2020-04-14
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 2010-10-01
      • 1970-01-01
      • 2012-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多