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

How to sort a multidimensional array

by benperl (Initiate)
on Jul 11, 2006 at 00:57 UTC ( [id://560284]=perlquestion: print w/replies, xml ) Need Help??

benperl has asked for the wisdom of the Perl Monks concerning the following question:

I've read for hours on the subject, but I have yet to see a comprehensive, working code model. Say I have an array with FirstName, LastName, Vocation. And @myArray looks something like:

Jeff Goldblum Actor
Mary Heartman Priest
John Ericsson Mathmetician
Tony Cisneros Chef


How can I sort on Vocation? I'm pretty good at PHP, but Perl is new, so if you could include ACTUAL script that works for this array - that would be awesome.

Thanks!

Replies are listed 'Best First'.
Re: How to sort a multidimensional array
by Zaxo (Archbishop) on Jul 11, 2006 at 01:30 UTC

    Ok. First, what you show looks like text data to perl, so I'll put it in DATA and read it like it's from a file.

    #!/usr/bin/perl my @multi_array; push @multi_array, [split] for <DATA>;
    I'm taking advantage of split's default arguments (split ' ', $_, where quoted space magically splits on and trims any amount of whitespace) and for's automatic loop variable, $_. The square brackets around split give me a reference to a copy of the array it produces.

    If you're feeling adventurous, you can replace that chunk with

    #!/usr/bin/perl # my @multi_array = map {[split]} <DATA>;
    uncommented.

    Vocation looks like it's at index 2, so we'll sort on that. Perl sort uses $a and $b as temporary storage for the two elements being compared.

    my @by_vocation = sort {$a->[2] cmp $b->[2]} @multi_array; for (@by_vocation) { print "@{$_}\n"; } __DATA__ Jeff Goldblum Actor Mary Heartman Priest John Ericsson Mathmetician Tony Cisneros Chef
    The trick is that multi-dimensional arrays in perl are just ordinary arrays, with array references as elements. Hence the arrow notation. You can work that idea as deep as you need to for many dimensions.

    After Compline,
    Zaxo

Re: How to sort a multidimensional array
by HuckinFappy (Pilgrim) on Jul 11, 2006 at 04:19 UTC
    Jeff Goldblum Actor Mary Heartman Priest John Ericsson Mathmetician Tony Cisneros Chef How can I sort on Vocation?
    Well, there's lots of ways of course!

    First off, I don't see any multidimensional array in your example. I just see a list of data. So let's make it a real multidimensional array:

    my @data = ( [ qw(Jeff Goldblum Actor) ], [ qw(Mary Heartman Priest) ], [ qw(John Ericsson Mathmetician) ], [ qw(Tony Cisneros Chef) ], );
    Ok, so now we have an array with 4 elements, each of which is a reference to an array of 3 elements. So now you want to sort on the Vocation, which is the third field. There are many approaches...personally I'm old school, and am a sworn Schwartzian Transform kind of guy:
    my @sorted = map { $_->[0] } # Line 4 sort { $a->[1] cmp $b->[1] } # Line 3 map { [ $_, $_->[2] ] } # Line 2 @data; # Line 1
    What the heck does that do? Read it backwards:
    1. Line #1 is your original list
    2. Line #2 - For each element in the original list, create an anonymous array of two elements: The first element in the array is the element fed in from the original array. The second element is field 2, which is the value of Vocation, or what you wanted to sort by
    3. Line #3 - Sort those anonymous arrays by field 1 (Vocation)
    4. Line #4 - As those anonymous array come out of sort, remap them to the original element from the unsorted @data.
    my @data = ( [ qw(Jeff Goldblum Actor) ], [ qw(Mary Heartman Priest) ], [ qw(John Ericsson Mathmetician) ], [ qw(Tony Cisneros Chef) ], ); my @sorted = map { $_->[0] } # Line 4 sort { $a->[1] cmp $b->[1] } # Line 3 map { [ $_, $_->[2] ] } # Line 2 @data; # Line 1 for ( @sorted ) { printf "%s %s - %s\n", @{ $_ }; }
    fappy@flux[16] perl /tmp/sortit Jeff Goldblum - Actor Tony Cisneros - Chef John Ericsson - Mathmetician Mary Heartman - Priest
    Hope this helps some,

    ~Jeff

Re: How to sort a multidimensional array
by salva (Canon) on Jul 11, 2006 at 07:18 UTC
    my @data = ('Jeff Goldblum Actor', 'Mary Heartman Priest', 'John Ericsson Mathmetician', 'Tony Cisneros Chef'); use Sort::Key 'keysort'; my @sorted = keysort { (split /\s+/, $_)[2]/ } @data;

      Assuming that you have your vocation as the third word
      in your array element string and ur strings delimited by exactly
      one space characters this also works

      @MYarray =( 'Jeff Goldblum Actor', 'Mary Heartman Priest', 'John Ericsson Mathmetician', 'Tony Cisneros Chef' ); @MYarray = map { join " ",@{$_} } sort { $a->[2] cmp $b->[2] } map{[sp +lit "\\s",$_]} @MYarray; use Data::Dumper; print Dumper(\@MYarray),"\n\n"; # your output should look like this .. $VAR1 = [ 'Jeff Goldblum Actor', 'Tony Cisneros Chef', 'John Ericsson Mathmetician', 'Mary Heartman Priest' ];
        This is great - I'm now trying to figure out how to get it to work with a comma-delimited array:
        Jeff,Goldblum,Actor Mary,Heartman,Priest John,Ericsson,Mathmetician Tony,Cisneros,Chef
        A reply falls below the community's threshold of quality. You may see it by logging in.
Re: How to sort a multidimensional array
by Mandrake (Chaplain) on Jul 11, 2006 at 07:18 UTC
    Try
    #!/usr/bin/perl -w use strict; my @arr = ("Jeff Goldblum Actor", "Mary Heartman Priest", "John Ericss +on Mathmetician","Tony Cisneros Chef") ; print $_."\n" foreach (sort {(split(" ", $a))[2] cmp (split(" ", $b))[ +2]}@arr);
    Thanks..

Log In?
Username:
Password:

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

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

    No recent polls found