Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Re: Help with multidimensional sorting on arrays of hashed arrays

by Clownburner (Monk)
on Mar 10, 2001 at 01:15 UTC ( [id://63368]=note: print w/replies, xml ) Need Help??


in reply to Re: Help with multidimensional sorting on arrays of hashed arrays
in thread Help with multidimensional sorting on arrays of hashed arrays

Close.. What I actually want to do is sort the 1st and 2nd values together, and then retrieve them in descending order. Effectively "flattening" two of the array values together (for this project, the third and fourth values are irrelevant). I'm thinking maybe something like this (does this make sense? I'm not sure what the first line will give me exactly...):
@newarray = (@alldata{data}[0], @alldata{data}[1]) @maxref = sort { $b->{data} <=> $a->{data} } @newarray
am I getting closer?

PS: I think my newbie status combined with this 3-dimensional array/hash/array structure has caused my cerebral cortex to rupture and leak my sanity out into the aether. :-P

Signature void where prohibited by law.
  • Comment on Re: Re: Help with multidimensional sorting on arrays of hashed arrays
  • Download Code

Replies are listed 'Best First'.
Re: Re: Re: Help with multidimensional sorting on arrays of hashed arrays
by arturo (Vicar) on Mar 10, 2001 at 02:35 UTC

    OK, for those onlookers: After extensive conversation in the chatterbox, Clownburner told me the following:

    {name} and {data} arrays map 1:1 onto each other, and the first two elements of the {data} array correspond to input and output rates, while the first two elements of the {name} array correspond to filenames.

    Clownburner wants a list of filenames sorted by greatest rates (input or output).

    First, get the list of name-value pairs for the first two values of {data} from @alldata

    my @names_and_rates = map { [ $_->{name}[0], $_->{data}[0] ], [ $_->{name}[1], $_->{data}[1] ] } @alldata;

    Now what you've got is an array, each element of which is an anonymous array consisting of a name -> rate pair. i.e.:

    @names_and_rates = ( [ name1, rate1], [name2, rate2], ... );

    What you want to do is sort that array by the second element of each anonymous array, i.e.

    my @final_list = sort { $b->[1] <=> $a->[1] } @names_and_rates; # $b first for descending order

    I think that will get you what you want. You can, of course, combine the two statements into one, e.g.

    my @final_list = sort { #sort stuff } map { #map stuff } @alldata;

    but I think that might be confusing if you come back to this code later, especially given the farrago of syntax. YMMV, IANAProfessional, etc.

    I hope this is right and that it helps.

    a nicety : if you want to print out the top n, do this:

    print "File\t\tRate\n"; foreach (@final_list[0 .. $n-1] ) { print $_->[0], "\t\t", $_->[1], "\n"; }

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

      Ok, we're nearly there.. but I have one mysterious problem I cannot understand:

      I inserted this code:
      my @names_and_rates = map { [ $_->{name}[0], $_->{data}[0] ],[ $_- +>{name}[1], $_->{data}[1] ] } @alldata; @maxref = sort { $b->[1] <=> $a->[1] } @names_and_rates; foreach (@maxref[0 .. 2] ) { print $_->[0], "\t\t", $_->[1]*8, "\n +<BR>"; }
      But got this:
      file      rate
                384434.306056 
                191966.35544 
                122524.077608 
      
      So clearly I'm missing the {name} parameter. So, I figured what I needed to do was flatten out the @alldata array a bit. I used this:
      Update Fixed a minor typo in the code below...
      my @maxtmp = sort { $b->{data} <=> $a->{data} } @alldata; my @names_and_rates = map { [ $_->{name}, $_->{data}->[0] ],[ $_-> +{name}, $_->{data}->[1] ] } @maxtmp; @maxref = sort { $b->[1] <=> $a->[1] } @names_and_rates; foreach (@maxref[0 .. 2] ) { print $_->[0], "\t\t", $_->[1]*8, "\n +<BR>"; }
      ..And it worked!
      Now I just need to know a more effective way than that first sort to flatten out the array, since the first sort operation (to @maxtmp) is wasted - but I didn't know how to use the map command to do the same thing.

      Any hints?!? Update 2: Thanks to arturo for the simple fix, below:
      my @names_and_rates = map { [ $_->{name}, $_->{data}->[0] ],[ $_-> +{name}, $_->{data}->[1] ] } @alldata; @maxref = sort { $b->[1] <=> $a->[1] } @names_and_rates; #this next bit just prints the top three foreach (@maxref[0 .. 2] ) { print $_->[0], "\t\t", $_->[1]*8, "\n +<BR>"; }

      Signature void where prohibited by law.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2024-04-24 01:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found