Traversing a multi-dimensional hash in Perl

后端 未结 8 1917
后悔当初
后悔当初 2021-01-03 04:02

If you have a hash (or reference to a hash) in perl with many dimensions and you want to iterate across all values, what\'s the best way to do it. In other words, if we hav

相关标签:
8条回答
  • 2021-01-03 04:24

    There's no way to get the semantics you describe because foreach iterates over a list one element at a time. You'd have to have deep_keys return a LoL (list of lists) instead. Even that doesn't work in the general case of an arbitrary data structure. There could be varying levels of sub-hashes, some of the levels could be ARRAY refs, etc.

    The Perlish way of doing this would be to write a function that can walk an arbitrary data structure and apply a callback at each "leaf" (that is, non-reference value). bmdhacks' answer is a starting point. The exact function would vary depending one what you wanted to do at each level. It's pretty straightforward if all you care about is the leaf values. Things get more complicated if you care about the keys, indices, etc. that got you to the leaf.

    0 讨论(0)
  • 2021-01-03 04:35

    Keep in mind that Perl lists and hashes do not have dimensions and so cannot be multidimensional. What you can have is a hash item that is set to reference another hash or list. This can be used to create fake multidimensional structures.

    Once you realize this, things become easy. For example:

    sub f($) {
      my $x = shift;
      if( ref $x eq 'HASH' ) {
        foreach( values %$x ) {
          f($_);
        }
      } elsif( ref $x eq 'ARRAY' ) {
        foreach( @$x ) {
          f($_);
        }
      }
    }
    

    Add whatever else needs to be done besides traversing the structure, of course.

    One nifty way to do what you need is to pass a code reference to be called from inside f. By using sub prototyping you could even make the calls look like Perl's grep and map functions.

    0 讨论(0)
提交回复
热议问题