【问题标题】:perl array processing at onceperl 数组一次处理
【发布时间】:2018-06-29 05:08:13
【问题描述】:

我有一个包含许多条目的数组,例如:

"a->b->c->x->n"
"something->something1->somethingelse"

我想一次从数组中提取所有奇数元素,并用它们的唯一值做一个哈希,比如:

%s = {
  "b" => '1'  
  #the values don't matter too much, they could be # occurences, I am going to use keys %s.
  "x" => '1'
  "something1" => '1'
}

目前我分几步执行此操作,但仅循环遍历数组会花费大量时间,因此我认为有办法做得更好。

my ( @odds, @evens );
foreach (@arr) {
  my $i = 0;
  push @{ $i++ % 2 ? \@odds : \@evens }, $_ for split /->/, $_;
}
%s = map {  $_ => '1'; } @odds;

对一次处理整个数组有什么建议吗?

【问题讨论】:

  • @ikegami:我见过一次处理整个数组的 perl 代码,例如使用 grep 或 map。我认为这可能比遍历每个条目更快。
  • 你错了。 grepmapfor 一样多的循环,并且将结果标量分配给数组的赋值同样循环所有标量。
  • 注释。 1) 使用for my $i (0..$#arr) 2) 只收集赔率 /// 否则,您必须访问每个元素,并且必须访问每个(第二个)子字符串。 (但试图访问每秒子字符串需要函数调用,它只会更慢。)
  • Re "grepmapfor 一样多的循环",实际上for(@a) BLOCKmap BLOCK @a 和@987654333 更有效@ 因为它被优化为迭代 @a 的索引,而 mapgrep@a 的所有元素放在堆栈上。

标签: arrays perl hash hashmap


【解决方案1】:

您的要求毫无意义。如果要对数组的每个元素执行某些操作,则必须循环遍历数组的每个元素(无论是否使用for)。

而且我没有在该代码中看到任何会很慢的内容(除非操作系统因为内存不足而开始使用虚拟内存)。填充@evens 并且从不使用它是一种浪费。

以下是您的代码的更简洁版本。它也更快(感谢pairvalues 并避免了临时存储),但实际上不应如此。

use List::Util qw( pairvalues );  # 1.29+

my %s;
for (@arr) {
   ++$s{$_} for pairvalues split /->/;
}

如果您不介意奇怪/丑陋的代码,下面的代码会更快(如果只是稍微):

use List::Util qw( pairvalues );  # 1.29+

my %s;
for (@arr) {
   undef @s{ pairvalues split /->/ };
}

【讨论】:

    【解决方案2】:

    如果您只对列表中具有奇数索引的元素感兴趣,那么 C 风格的 for 循环是显而易见的选择

    use strict;
    use warnings 'all';
    
    my @arr = ( "a->b->c->x->n", "something->something1->somethingelse" );
    
    my %s;
    
    for ( @arr ) {
    
        my @k = split /->/;
    
        for ( my $i = 1; $i < @k; $i += 2 ) {
            $s{ $k[$i] } = 1;
        }
    }
    
    use Data::Dumper;
    print Dumper \%s;
    

    输出

    $VAR1 = {
              'b' => 1,
              'x' => 1,
              'something1' => 1
            };
    

    如果-&gt; 之间的值确实像您描述的那样表现良好,您可能还需要考虑正则表达式解决方案。这假定列表总是包含奇数个字符。

    for ( @arr ) {
        $s{ $1 } = 1 while /->(\w+)->/g;
    }
    

    这个循环的结果和前面的代码是一样的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 2014-01-04
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      相关资源
      最近更新 更多