我有一个递归函数,使用ref递归地向下走数据结构。如果ref返回一个空字符串,则调用一个回调。我的问题是我需要在我的数据结构中存储一个hash-ref,它将被我的函数视为标量。
从本质上讲,我需要的是做这样的事情;
my %hash = fillHash();
$hash{'abc'}{'def'} = \%hash;
我想知道是否存在以某种方式存储\%hash的方式,它将被视为标量而不是引用。可能喜欢/
$hash{'abc'}{'def'} = scalar \%hash;
我只是想找到一种方法来添加一个链接到我的数据结构的父节点,但仍然可以递归地遍历它。
由于
答案 0 :(得分:3)
您可以使用我所做的来区分值与结构,我称之为“间接数组”(在我的情况下)。
在你的情况下,它看起来像这样:
$hash{'abc'}{'def'} = scalar \\%hash;
ref( $hash{'abc'}{'def'} )
是'REF'
,以防你想知道。然后,您可以决定需要取消引用它两次:
$hash_ref = ${ $hash{'abc'}{'def'} };
答案 1 :(得分:2)
我认为@MarkCanlas在他的建议中有正确的解决方案,可以考虑采用不同的方式来构建数据。除此之外,你可以采取双重参考。
my $scalar_ref = \%hash;
$other_hash{abc}{def} = \$scalar_ref;
现在,当您检查ref
时,您将返回"REF"
并可以执行其他操作。
答案 2 :(得分:1)
首先,您应该意识到所有引用都是定义的标量。
你想要的东西在任何地方都可以作为参考,但在你的步行功能中。任何神奇的参考都无法实现这一点。步行功能是必须添加逻辑的地方。你可以让它跟踪它已经看到的东西:
my %h = (
foo => "bar",
inner => {
foo => 42
}
);
$h{inner}{parent} = \%h;
sub walk
{
my ($h, $cb, $path, $seen) = @_;
$path //= "";
$seen //= {};
$seen->{$h}=1;
while(my ($k, $v) = each %$h) {
if(ref($v)) {
walk($v, $cb, "$path/$k", $seen) if !$seen->{$v};
} else {
$cb->($k, $v, "$path/$k");
}
}
}
walk(\%h, sub {
my ($key, $value, $path) = @_;
print "walker found $key ($path) => $value\n";
});
或者您可以让它将parent
之类的某些键识别为特殊并跳过它们。