Arrays 如何从Perl哈希中删除空数组/引用?
假设我有以下Perl哈希:Arrays 如何从Perl哈希中删除空数组/引用?,arrays,perl,hash,Arrays,Perl,Hash,假设我有以下Perl哈希: %hash = ( 'A' => { 'B' => ['C', 'D', 'E'], 'F' => { 'G' => [], 'H' => [] }, 'I' => [] } ); 我想去掉[],得到下面的散列结果: %hash = ( 'A' => [ 'B' => ['C', 'D', 'E'],
%hash = (
'A' => {
'B' => ['C', 'D', 'E'],
'F' => { 'G' => [], 'H' => [] },
'I' => []
} );
我想去掉[]
,得到下面的散列结果:
%hash = (
'A' => [
'B' => ['C', 'D', 'E'],
'F' => [ 'G', 'H', 'I' ]
]
)
(我希望我的
{}
和[]
得到了平衡,如果没有,我深表歉意,但是)基本上我想让它不存在空数组/ref。我确信这是可能的/简单的,但我不确定delete()
是否有效,或者是否有更好的方法或Perl模块。有人能把我引向正确的方向吗?看起来您的数据可能是任意嵌套的,您希望递归地遍历它,将某些模式重写为其他模式。为此,我将使用Data::Visitor
use Data::Visitor::Callback;
use List::MoreUtils 'all';
my $visitor = Data::Visitor::Callback->new(
hash => sub {
my ($self, $href) = @_;
# fold hashrefs with only empty arrayrefs as values into arrayrefs
if (all { ref $_ eq 'ARRAY' && !@{ $_ } } values %{ $href }) {
return [ keys %{ $href } ];
}
# strip k/v pairs with an empty arrayref as a value
return {
map {
$_ => $href->{$_}
} grep {
ref $href->{$_} ne 'ARRAY' || @{ $href->{$_} }
} keys %{ $href }
};
},
);
my %new_hash = %{ $visitor->visit(\%hash) };
这只是说明了我将使用的基本方法,并且恰好适用于您提供的示例输入。它可能需要各种调整,这取决于您在其他注释中指出的角落案例中想要做什么。[这应该是一条注释,但我需要格式。] 你的问题令人费解。(1) 根据什么原则,
I
键(来自原始散列)会在F
键的列表中结束(在预期散列中)?(2) 如果F
包含空数组引用之外的内容(请参见我对原始哈希的添加),会发生什么
遍历散列(树,无论什么)是任何程序员都应该知道的技术,但在某些情况下,我认为治疗几乎比疾病更糟糕
您的预期输出是否符合您的预期?你在课文中所说的似乎不同。我在我的例子中使用了他的哈希
如果你使用队列,这很容易。从顶级散列开始。每次遇到哈希引用时,都会将其添加到队列中。当您遇到数组ref时,检查它是否有值,如果没有,则删除该键。你留下的一切:
#!perl
use strict;
use warnings;
use 5.010;
my %hash = ( # From FM
'A' => {
'B' => ['C', 'D', 'E'],
'F' => {
'G' => [],
'H' => [],
'Z' => ['FOO', 'BAR'], # Not in the OP's original.
},
'I' => [],
},
);
my @queue = ( \%hash );
while( my $ref = shift @queue ) {
next unless ref $ref eq ref {};
KEY: foreach my $key ( keys %$ref ) {
if( ref $ref->{$key} eq ref {} ) {
push @queue, $ref->{$key};
next KEY;
}
elsif( ref $ref->{$key} eq ref [] ) {
delete $ref->{$key} if @{$ref->{$key}} == 0;
}
}
}
use Data::Dumper;
print Dumper( \%hash );
我的输出是:
$VAR1 = {
'A' => {
'F' => {
'Z' => [
'FOO',
'BAR'
]
},
'B' => [
'C',
'D',
'E'
]
}
};
该输出听起来更像您所要求的,而不是您指定的重组。您能澄清输出吗?是否打算让
I
完全消失,而G
和H
只是折叠成一个列表?您可以将“F”从所有值都是空arrayrefs的hashref转换为arrayref。如果“F”有一个非空值,比如'F'=>{G=>[],H=>[],J=>'K'}
,会怎么样?对不起,它没有在a和F下保留G,H和I,但是谢谢你的回答。你能解释一下保存这些元素的规则吗?这并不难做到,但我总是担心从一个单独的例子工作。谢谢rafl!这正是我需要的!
$VAR1 = {
'A' => {
'F' => {
'Z' => [
'FOO',
'BAR'
]
},
'B' => [
'C',
'D',
'E'
]
}
};