goal:从阵列中删除特定的value 我写了一个脚本,它的工作正常,但是我不高兴的写作方式。因此,我很想知道有一种更好的写作方法。请考虑以下用例:
我有一个嵌套的哈希/哈希/数组...如下所示。我需要删除任何具有其名称的数组值:
local
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $hash = { esx1 =>
{ cluster => "clu1",
fd => "fd1",
ds => [
'ds1',
'ds2',
'localds',
],
},
esx2 =>
{ cluster => "clu2",
fd => "fd2",
ds => [
'ds3',
'ds4',
'dslocal',
],
},
};
foreach my $a ( keys %$hash )
{
foreach ( 0..$#{ $hash->{$a}->{ds} } )
{
delete $hash->{$a}->{ds}->[$_] if $hash->{$a}->{ds}->[$_] =~ /local/i;
@{ $hash->{$a}->{ds} } = grep defined, @{ $hash->{$a}->{ds} };
}
}
print Dumper ($hash);
”和“
localds
”,并使其他所有内容保持完整。
有一种更清洁的方式来编写dslocal
循环?foreach ( 0..$#{$hash->{$a}->{ds} } )
线,则结果数组的值包含grep
local
替换为undef
。为什么这会发生?
对于数组,您要使用剪接。
splice @{ $ref->{to}->{array} }, $index, 1, ();
this thim替换为1元素的sublist,从$index
开始,用空列表开始。
为什么首先通过数组迭代并删除元素,然后查找“未删除”节点(旁注 - 此()
应该在室外循环)?您可以从一开始就可以寻找好的节点!用以下方式替换整个循环
grep
不多,而是:
for my $h (values %$hash){
$h->{ds} = [ grep { $_ !~ /local/i } @{$h->{ds}} ];
}
delete不会改变数组结构,而只是改变数组内容。由于您的方法,您需要抓取定义的条目以创建所需结构的新数组,然后覆盖旧数组。
delete()也可以在数组和阵列切片上使用,但其行为不那么简单。尽管存在()将返回已删除条目的false,但删除数组元素永远不会更改现有值的索引;为此使用shift()或剪接()。但是,如果所有已删除的元素都落在数组的末尾,则数组的大小会缩小到最高元素的位置,该位置仍然测试了已存在的最高元素,或者如果没有测试,则缩小到0。
被暴民剪接指出的是您想要的事情:
foreach my $a ( keys %$hash )
{
my $temp;
foreach ( @{ $hash->{$a}->{ds} } )
{
push(@$temp, $_) unless $_ =~ /local/i;
}
$hash->{$a}->{ds} = $temp;
}
您可以使用list :: moreutils qw/ first_idx/获取/ local/ likeso的索引
foreach my $a ( keys %$hash )
{
for(0..$#{ $hash->{$a}->{ds} } )
{
splice( @{ $hash->{$a}->{ds} }, $_, 1 ) if $hash->{$a}->{ds}->[ $_ ] =~ /local/i;
}
}
然后做你想做的事。