in reply to Filter array of hashes for specific keys

So what code have you already written and where did you encounter problems? Where does your code produce different results from what you expect and how are they different?

  • Comment on Re: Filter array of hashes for specific keys

Replies are listed 'Best First'.
Re^2: Filter array of hashes for specific keys
by ddominnik (Novice) on Oct 21, 2016 at 09:45 UTC

    So far I've tried it myself this way:

    sub filter { die 'Error: no fields to filter through' if (@_ < 2); my $response = shift; my @fields; foreach my $a (0..$#_) { $fields[$a]= shift; } if (ref $response eq 'ARRAY') { my @response = @$response; my @filtered_responsearr; my %filtered_response; foreach my $ref (@response) { my %response = %$ref; foreach my $field (@fields) { $filtered_response{$field}=$response{$field}; } push @filtered_responsearr, %filtered_response; } return \@filtered_responsearr; }

    which returns an array of all the fields, like ['name','foo','id','bar','name','foo2','id','bar2']
    But I don't need an array of all the fields, I need an array of hashes, because I have to work with the hashes afterwards

      You want to push a hash reference and not a hash:

      push @filtered_responsearr, \%filtered_response;

      Your code can be greatly simplified in some other places:

      my $response = shift; my @fields; foreach my $a (0..$#_) { $fields[$a]= shift; }

      can be rewritten as a single assignment:

      my( $response, @fields ) = @_;

      Likewise, copying the elements of %response into the filtered response can be done using a hash slice instead of the loop:

      @filtered_response{ @fields } = @response{ @fields }

        %filtered_response is declared only once in the function call, so every reference to it will be identical. { %filtered_response } would work, but it would be better to move the declaration of %filtered_response inside the for loop.

        Or, with a recent enough version of perl, you can use a pairwise slice: push @filtered_responsearr, { %response{ @fields } };.
        With a postfix dereference: push @filtered_responsearr, { $res->%{ @fields } }

        Edit: I added the missing { } in the last line, to have a hash reference and not pairs of values.

        Wow, thanks for the tips, didn't know about hash slice. I'm just getting started so please forgive me my noobness. I tried what you said but it just gave me the same hash over and over, but Eily's answer solved that as well. Thanks to you both!
      foreach my $a (0..$#_) { $fields[$a]= shift; }
      Avoid using $a and $b as variables, give them other names ;) .
      perlvar -> $a, $b