perl数组处理一次

时间:2018-01-19 21:37:19

标签: arrays perl hash hashmap

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

"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;

立即处理整个阵列的任何建议?

2 个答案:

答案 0 :(得分:3)

你的要求毫无意义。如果要对数组的每个元素执行某些操作,则必须遍历数组的每个元素(无论是否使用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 /->/ };
}

答案 1 :(得分:1)

如果您只对那些具有奇数索引的列表元素感兴趣,那么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
        };

如果->之间的值与您描述的一样好,那么您可能还需要考虑使用正则表达式解决方案。这假定列表总是包含奇数个字符。

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

此循环的结果与前一代码的结果相同