Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

(tye)Re: Efficient random hash stuff

by tye (Sage)
on Nov 17, 2000 at 01:18 UTC ( [id://42082]=note: print w/replies, xml ) Need Help??


in reply to Efficient random hash stuff

Ah, no need to splice.

# @keys = keys %hash; # done ONCE # ($k,$v) = rhe(%hash,@keys); sub rhe (\%\@) { my( $hv, $av )= @_; my $idx= rand @$av; my $key= $av->[$idx]; my $val= delete $hv->{$key}; my $last= pop @$av; $av->[$idx]= $last if $idx < @$av; return( $key, $val ); }

As for saving space, I don't see you really making use of the hash here so you could do:

@keys = keys %hash; @vals = values %hash; undef %hash;
If the keys are long, then you could also probably save a bit of space by storing reference to the keys in the array instead of the key values themself (or maybe not).

        - tye (but my friends call me "Tye")

Replies are listed 'Best First'.
Re: (tye)Re: Efficient random hash stuff
by japhy (Canon) on Nov 17, 2000 at 01:28 UTC
    Wow, that's damn nice. And we could use my just-an-array idea from above:
    sub rand_element (\@); @array = ([1,2], [3,4], [5,6]); # etc... ($k,$v) = rand_element(@array); sub rand_element (\@) { my $aref = shift; my $idx = rand @$aref; my ($k,$v) = @{ $aref->[$idx] }; my $last = pop @$aref; $aref->[$idx] = $last if $idx < @$aref; return ($k,$v); }
    Thank you muchly, tye. I need to ++ YOU, not your node...

    $monks{japhy}++ while $posting;

      Note that ([1,2],[3,4],[5,6],...) consumes quite a bit more memory (no, I haven't tested this) than ( [1,3,5,...], [2,4,6,...] ). I agree that this is less elegant, but if memory usage is a primary concern, then the elegance loss might be worth it.

              - tye (but my friends call me "Tye")
        Ok, modified thus:
        sub rand_element (\@); @array = ([1,3,5], [2,4,6]); # [keys], [values] ($k,$v) = rand_element(@array); sub rand_element (\@) { my $aref = shift; my $idx = rand @{$aref->[0]}; my ($k,$v) = ($aref->[0][$idx], $aref->[1][$idx]); my @last = (pop @{$aref->[0]}, pop @{$aref->[1]}); ($aref->[0][$idx],$aref->[1][$idx]) = @last if $idx < @{$aref->[0]}; return ($k,$v); }
        While not tested, I do belive it works -- the code has been changed only to allow for the different structure.

        Thanks again, tye/Tye.

        $monks{japhy}++ while $posting;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://42082]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-04-25 23:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found