回答
这是你想要的吗? (未经测试)
sub for_hash {
my ($hash, $fn) = @_;
while (my ($key, $value) = each %$hash) {
if ('HASH' eq ref $value) {
for_hash $value, $fn;
}
else {
$fn->($value);
}
}
}
my $example = {'key' => {'key2' => {'key3' => 'value'}}};
for_hash $example, sub {
my ($value) = @_;
# Do something with $value...
};
我喜欢你的Yoda条件在第四行:) – 2013-08-05 08:08:22
foreach my $keyname (keys(%foo) {
my $subhash = $foo{$keyname};
# stuff with $subhash as the value at $keyname
}
这应该是$ foo {$ keyname}而不是%foo {$ keyname}! – 2010-03-02 13:06:33
所以它应该。这就是我在咖啡之前发布的内容。 – monksp 2010-03-02 13:12:15
你将不得不循环两次。即
while (($family, $roles) = each %HoH) {
print "$family: ";
while (($role, $person) = each %$roles) {
print "$role=$person ";
}
print "\n";
}
另外,请通读perldoc perldsc。你可以深入了解哈希值
This post可能是有用的。
foreach my $key (keys %hash) {
foreach my $key2 (keys %{ $hash{$key} }) {
foreach my $key3 (keys %{ $hash{$key}{$key2} }) {
$value = $hash{$key}{$key2}->{$key3};
# .
# .
# Do something with $value
# .
# .
# .
}
}
}
这个答案建立在Dave Hinton的背后 - 即写一个通用子程序来散步散列结构。这样的散列函数需要一个代码引用,并简单地为散列中的每个叶节点调用该代码。
使用这种方法,可以使用相同的散列函数来做很多事情,具体取决于我们给出的回调函数。为了获得更大的灵活性,您需要传递两个回调函数 - 一个在值为哈希引用时调用,另一个在普通标量值时调用。 Marc Jason Dominus的优秀书籍Higher Order Perl更深入地探讨了这样的策略。
use strict;
use warnings;
sub hash_walk {
my ($hash, $key_list, $callback) = @_;
while (my ($k, $v) = each %$hash) {
# Keep track of the hierarchy of keys, in case
# our callback needs it.
push @$key_list, $k;
if (ref($v) eq 'HASH') {
# Recurse.
hash_walk($v, $key_list, $callback);
}
else {
# Otherwise, invoke our callback, passing it
# the current key and value, along with the
# full parentage of that key.
$callback->($k, $v, $key_list);
}
pop @$key_list;
}
}
my %data = (
a => {
ab => 1,
ac => 2,
ad => {
ada => 3,
adb => 4,
adc => {
adca => 5,
adcb => 6,
},
},
},
b => 7,
c => {
ca => 8,
cb => {
cba => 9,
cbb => 10,
},
},
);
sub print_keys_and_value {
my ($k, $v, $key_list) = @_;
printf "k = %-8s v = %-4s key_list = [%s]\n", $k, $v, "@$key_list";
}
hash_walk(\%data, [], \&print_keys_and_value);
这帮了我很多,谢谢 – 2010-03-03 13:39:33
较早的答案显示如何推出自己的解决方案,这是很好的做至少一次,以便您了解如何perl的引用和数据结构工作的胆量。如果您尚未阅读,您应该仔细阅读perldoc perldsc和perldoc perlref。
但是,您不需要编写自己的解决方案 - CPAN上已经有一个模块,它将通过任意复杂的数据结构迭代:Data::Visitor。
+1谢谢,'Data :: Visitor'看起来很有用。从文档看,如何做一些简单的事情并不是很明显 - 例如,遍历嵌套的散列结构,打印叶节点值和它们的键(直接和他们的祖先)。我相信这是可行的。只需要将我的头包裹一下就可以了。 :) – FMc 2010-03-02 20:05:18
这不是一个真正的新答案,但我想分享如何做超过 只是递归地打印所有的散列值,但如果需要也可以修改它们。
这是我在 值传递给回调作为参考,所以我的回调 程序可以再修改中的散列值每的dave4420的答案曾经如此轻微的修改。
我也不得不重建散列,因为每个循环创建副本 没有引用。
sub hash_walk {
my $self = shift;
my ($hash, $key_list, $callback) = @_;
while (my ($k, $v) = each %$hash) {
# Keep track of the hierarchy of keys, in case
# our callback needs it.
push @$key_list, $k;
if (ref($v) eq 'HASH') {
# Recurse.
$self->hash_walk($v, $key_list, $callback);
}
else {
# Otherwise, invoke our callback, passing it
# the current key and value, along with the
# full parentage of that key.
$callback->($k, \$v, $key_list);
}
pop @$key_list;
# Replace old hash values with the new ones
$hash->{$k} = $v;
}
}
hash_walk(\%prj, [], \&replace_all_val_strings);
sub replace_all_val_strings {
my ($k, $v, $key_list) = @_;
printf "k = %-8s v = %-4s key_list = [%s]\n", $k, $$v, "@$key_list";
$$v =~ s/oldstr/newstr/;
printf "k = %-8s v = %-4s key_list = [%s]\n", $k, $$v, "@$key_list";
}
如果您正在使用Perl作为一个 “CPAN解释” 那么除了Data::Visitor
和有超级简单Data::Traverse
:
use Data::Traverse qw(traverse);
my %test_hash = (
q => [qw/1 2 3 4/],
w => [qw/4 6 5 7/],
e => ["8"],
r => {
r => "9" ,
t => "10" ,
y => "11" ,
} ,
);
traverse { next if /ARRAY/; print "$a => $b\n" if /HASH/ && $b > 8 } \%test_hash;
输出:
t => 10
y => 11
$a
和$b
被视为特殊变量在这里(和sort()
一样),而在traverse()
函数中。 Data::Traverse
是一个非常简单但非常有用的模块,没有非CORE依赖关系。
- 1. 如何在perl中使用hash和getopts
- 2. 在Perl中包含Hashes内的哈希
- 3. 如何迭代Perl PDL piddle?
- 4. Perl hash Data :: Dumper
- 5. Perl array hash print
- 6. 如何迭代Perl数组引用?
- 7. Decode Hash :: MultiValue in perl
- 8. Array to a hash perl
- 9. 在perl中迭代哈希值
- 10. 什么@ {hash {$ key}}在Perl中的含义?
- 11. 如何在Perl中同时迭代多个列表?
- 12. 在Perl中,我如何迭代数组的多个元素?
- 13. 如何在[perl]中将散列[hashes] *的散列值作为CSV打印
- 14. 如何获得no的数量。密钥在perl 6%HASH中?
- 15. 如何在Ruby中迭代?
- 16. Perl:在Perl-Hash中存储来自Mysql-table的列
- 17. 帮助理解perl hash
- 18. 在hash参数上迭代调用self.send来初始化()
- 19. perl中的散列键迭代
- 20. 如何迭代Perl中的正则表达式匹配变量?
- 21. 删除perl hash中的冗余
- 22. 在Perl中,if(%hash)和if(定义的%hash)之间有什么区别?
- 23. 如何迭代使用迭代器
- 24. 如何迭代GLMS在H2O
- 25. 在Perl中,如何迭代多个集合的笛卡尔乘积?
- 26. 使用`each`对hash进行迭代不像预期的那样
- 27. 如何在迭代中“取消”元素
- 28. 如何在JavaScript中迭代字符串?
- 29. 如何在Matlab中迭代列向量?
- 30. 如何在C++中递减迭代器?
你可以举一个更现实的例子。你在哪里遇到这样的结构?它是干什么用的?您想做什么? 也许另一个数据结构会更适合这项任务? – Aurril 2010-03-02 13:04:19
@Aurril:嵌套散列结构对许多事情都很有用,请参阅下面我的帖子中的链接。 – Zaid 2010-03-02 13:13:24
每个散列都有多个键吗? – Svante 2010-03-02 13:22:32