我有一个包含许多条目的数组,如:
"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;
立即处理整个阵列的任何建议?
答案 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;
}
此循环的结果与前一代码的结果相同