Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

array => hash of occurrence indexes

by pldanutz (Acolyte)
on Sep 11, 2013 at 10:53 UTC ( #1053457=perlquestion: print w/replies, xml ) Need Help??
pldanutz has asked for the wisdom of the Perl Monks concerning the following question:

Better / shorter ways to write this? It takes a list and returns a hash of arrays (key => list of indices where key appears in argument)
use 5.012; use warnings; use Data::Dumper; sub occurrences { my %h; while (my ($i, $k) = each (@_)) { if (! $h {$k}) { $h {$k} = [] } push $h {$k}, $i } return %h } my %h = occurences (2, 1, 3, 4, 3, 4, 4, 5 ); print Dumper (\%h)'

Replies are listed 'Best First'.
Re: array => hash of occurrence indexes
by BrowserUk (Pope) on Sep 11, 2013 at 11:17 UTC

    Not so much shorter, but avoids the 5.12 dependency:

    sub occurs{ my %h; push @{ $h{ $_[$_] } }, $_ for 0 .. $#_; return \%h };; pp occurs( 2, 1, 3, 4, 3, 4, 4, 5 );; { 1 => [1], 2 => [0], 3 => [2, 4], 4 => [3, 5, 6], 5 => [7] }

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: array => hash of occurrence indexes
by kcott (Chancellor) on Sep 12, 2013 at 05:19 UTC

    G'day pldanutz,

    I generally think it's better to pass around scalars than entire data structures, so returning a reference to that hash would be my preference.

    If you wrapped $h{$k} in @{...}, you could dispense with if (! $h {$k}) { $h {$k} = [] } entirely.

    Even if you're using 5.012 for other reasons elsewhere in your code, I see little, if any, value in using each here. It's easy to write it for any Perl5.

    Putting all that together, you could code occurrences() like this instead:

    sub occurences { my %h; my $i = 0; push @{$h{$_}}, $i++ for @_; return \%h; }

    If you were looking for a golf answer, you could start with the following and then proceed to remove whitespace until illegibility was achieved. :-)

    sub occurences { my ($i, %h) = 0; push @{$h{$_}}, $i++ for @_; \%h }

    Here's my tests:

    -- Ken

Re: array => hash of occurrence indexes
by choroba (Chancellor) on Sep 11, 2013 at 11:20 UTC
    Pushing to the $i? That is a bit too much for 5.12.
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Fixed. Didn't copy/paste from the right source.
        Please, mark changes to the original IN the original... and include a note that the post has been updated, in the post. Do NOT delete/replace; use strikeouts.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1053457]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2017-04-27 04:17 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (500 votes). Check out past polls.