in reply to Re: SQL like query over iterable in perl
in thread SQL like query over iterable in perl

More generic than haukex's, more pure-perl than Athanasius's, more functional than OO

Shorter than huck's ;-P

sub count { my ($data, $fields) = @_; $fields = [$fields] unless ref $fields; my $count = {}; for my $obj (@$data) { my $ref = $count; $ref = $ref->{ $obj->{ $fields->[$_] } } //= {} for 0..$#$fields-1; $ref->{ $obj->{ $fields->[-1] } }++; } return $count; }

(For input, output and other context see my other node)

Replies are listed 'Best First'.
Re^3: SQL like query over iterable in perl
by huck (Prior) on Mar 02, 2017 at 09:30 UTC

    Cute

    Made me think $fields = [$fields,@_] unless ref fields;

    and not that it matters here, and i would have to look up funny debug commands to tell for sure, but are $#$fields-1 and $fields->[-1] optimized or does the subtraction happen every loop of $obj? Im never sure.

    and in mine, besides $data,$fields,and $count as nicer variable names, i had already decided i should have $size1 be named as $nterminal and $size2 named as $nsubparts to make it clearer what they did. wasnt gun'a post as a "fix" but this gave me an excuse to mention it.

    Edited to add: What about missing fields? $ref = $ref->{ $obj->{ $fields->[$_] // '.' } } //= {} where '.' is used like the SAS missing variable.
    That wasnt right, instead $ref = $ref->{ $obj->{ $fields->[$_] } // '.'  } //= {}

      I hope it's clear I wasn't being entirely serious or saying that my code was "better", it was just a lighthearted retort :-)

      i would have to look up funny debug commands to tell for sure, but are $#$fields-1 and $fields->[-1] optimized or does the subtraction happen every loop

      I'm not sure either, but I'd have to guess no, since the optimizer would have to know for certain that @fields won't change, and in a language as dynamic as Perl, that's probably very rarely the case, if ever. As for the debug command, I assume you're thinking of B::Deparse, invoked as perl -MO=Deparse script.pl, which would show, for example, constant folding.

      I did a quick test with Benchmark and refactored out $fields->[-1] and $#$fields-1 to before the loop, and that gave a consistent but small speed increase of ~5% (although IIRC, in terms of Benchmark results that's still in the margin of error of being insignificant).

      I didn't take missing fields into account because the OP was asking about objects, but you have a good point there, my code doesn't properly handle undef values (or an empty @$fields for that matter).

      Actually I have quite similar function that dynamically creates nested hash counter. That gives confirmation that I'm in the right direction. :) Thanks.