对于此格式的哈希:
my $itemHash = { tag1 => { name => "Item 1",order => 1,enabled => 1,},tag2 => { name => "Item 2",order => 2,enabled => 0,tag3 => { name => "Item 3",order => 3,... }
我有这个代码正确迭代哈希:
keys %$itemHash; # Resets the iterator while(my($tag,$item) = each %$itemHash) { print "$tag is $item->{'name'}" }
但是,迭代这些项的顺序似乎很随机.是否可以使用相同的while格式按照每个项目的哈希中“order”键指定的顺序迭代它们?
(我知道我可以先对键进行排序,然后再循环遍历它.只是想看看是否有更简洁的方法来执行此操作.)
解决方法
“有序哈希”的概念是错误的.虽然数组是元素的有序列表,因此可以通过索引访问,但是散列是键值对的(无序)集合,其中键是一组.
要完成任务,您必须按order属性对键进行排序:
my @sorted = sort {$hash{$a}{order} <=> $hash{$b}{order}} keys %$itemHash;
然后,您可以通过map创建键值对:
my @sortedpairs = map {$_ => $itemHash->{$_}} @sorted;
我们可以把它包装成一个子:
sub ridiculousEach { my %hash = @_; return map {$_ => $hash{$_}} sort {$hash{$a}{order} <=> $hash{$b}{order}} keys %hash; }
获得一个大小合适的键值元素列表,以及
sub giveIterator { my %hash = @_; my @sorted = sort {$hash{$a}{order} <=> $hash{$b}{order}} keys %hash; return sub { my $key = shift @sorted; return ($key => $hash{$key}); }; }
创建一个回调,它是每个回调的一个插件.
然后我们可以这样做:
my $iterator = giveIterator(%$itemHash); while (my ($tag,$item) = $iterator->()) { ...; }
这种方法存在严重的缺点:每种方法一次只使用两个元素,因此在恒定的存储器中运行.此解决方案必须读取整个哈希并存储所有键的数组.对于小哈希来说不明显,这对于非常大量的元素来说非常重要.