sorting a structure

B

Brett

Jürgen Exner said:
Indeed, there is: use a data structure that matches your problem better.
Instead of having a pair of unrelated arrays use a single array of pairs.
And then sort that single array by the value of the first component of each
pair.

jue


I'm new to this, and tried to give it a go.

use Class::Struct;

struct ID =>
{
number => '$',
name => '$',
};

my @IDs = ID->new();
#fill data...

@IDs = sort {$a->number <=> $b->number} (@IDs); # numeric sort on number

but that failed to sort the list as i expected. How can i use sort on a
structure to do
what I want?
 
S

Steven Kuo

I'm new to this, and tried to give it a go.

use Class::Struct;


Haven't seen anything in your description that requires OO-style
programming.

struct ID =>
{
number => '$',
name => '$',
};

my @IDs = ID->new();
#fill data...


The constructor returns a single item (a blessed reference); I'm not
sure why you would want to store it into an array though.

@IDs = sort {$a->number <=> $b->number} (@IDs); # numeric sort on number


Are your sorting an array containing just a single item?

but that failed to sort the list as i expected. How can i use sort on a
structure to do
what I want?


I think this is more along the lines of what Jürgen suggested:

use strict;
use warnings;
use List::MoreUtils qw(pairwise);

my @l1 = (3, 1, 2);
my @l2 = qw(a b c);

my @numbers_sorted;
my @letters_mapped;

for my $aref (
sort { $a->[0] <=> $b->[0] }
pairwise { [$a, $b] } @l1, @l2
) {
push @numbers_sorted, $aref->[0];
push @letters_mapped, $aref->[1];
}
 
A

Anno Siegel

Steven Kuo said:
[snippage]

I think this is more along the lines of what Jürgen suggested:

use strict;
use warnings;
use List::MoreUtils qw(pairwise);

[presumably correct implementation snipped]

However, regrouping the data structure is not strictly necessary. Indirect
sorting is an age-honored technique of ordering one list according to
another. You first sort a list of indices to the numeric array according
to the values in that array. Then you take the elements of the second
array in sequence of the indices:

my @l1 = qw( 3 1 2);
my @l2 = qw( a b c);
my @l2_sorted = @l2[ sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1];

Anno
 
S

Steven Kuo

Steven Kuo said:
I think this is more along the lines of what Jürgen suggested:

use strict;
use warnings;
use List::MoreUtils qw(pairwise);

[presumably correct implementation snipped]

However, regrouping the data structure is not strictly necessary. Indirect
sorting is an age-honored technique of ordering one list according to
another. You first sort a list of indices to the numeric array according
to the values in that array. Then you take the elements of the second
array in sequence of the indices:

my @l1 = qw( 3 1 2);
my @l2 = qw( a b c);
my @l2_sorted = @l2[ sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1];



I like it!

To efficiently generate two sorted arrays, one would presumably save the
sorted indices:

my @sorted_idx = sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1 ;

my @l1_sorted = @l1[ @sorted_idx ];
my @l2_sorted = @l2[ @sorted_idx ];

Thanks for the tip.
 
T

Tad McClellan

Brett said:
Subject: sorting a structure


Please get your newsreader configured to generate proper followups.

Missing the "Re: " in the Subject header isn't so bad,
but having no References: header breaks the thread.



[snip]
 
A

Anno Siegel

Steven Kuo said:
Steven Kuo said:
I think this is more along the lines of what Jürgen suggested:

use strict;
use warnings;
use List::MoreUtils qw(pairwise);

[presumably correct implementation snipped]

However, regrouping the data structure is not strictly necessary. Indirect
sorting is an age-honored technique of ordering one list according to
another. You first sort a list of indices to the numeric array according
to the values in that array. Then you take the elements of the second
array in sequence of the indices:

my @l1 = qw( 3 1 2);
my @l2 = qw( a b c);
my @l2_sorted = @l2[ sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1];



I like it!

To efficiently generate two sorted arrays, one would presumably save the
sorted indices:

my @sorted_idx = sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1 ;

my @l1_sorted = @l1[ @sorted_idx ];
my @l2_sorted = @l2[ @sorted_idx ];

Yes, that's when indirect sorting really begins to pay. You sort
only once (n*log n), then re-arrange any number of arrays in linear
time.

Anno
 
B

Brett

Anno Siegel said:
Steven Kuo said:
I think this is more along the lines of what Jürgen suggested:

use strict;
use warnings;
use List::MoreUtils qw(pairwise);

[presumably correct implementation snipped]

However, regrouping the data structure is not strictly necessary. Indirect
sorting is an age-honored technique of ordering one list according to
another. You first sort a list of indices to the numeric array according
to the values in that array. Then you take the elements of the second
array in sequence of the indices:

my @l1 = qw( 3 1 2);
my @l2 = qw( a b c);
my @l2_sorted = @l2[ sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1];



I like it!

To efficiently generate two sorted arrays, one would presumably save the
sorted indices:

my @sorted_idx = sort { $l1[ $a] <=> $l1[ $b] } 0 .. $#l1 ;

my @l1_sorted = @l1[ @sorted_idx ];
my @l2_sorted = @l2[ @sorted_idx ];

Yes, that's when indirect sorting really begins to pay. You sort
only once (n*log n), then re-arrange any number of arrays in linear
time.

Anno


Thanks for your help. Thats the answer that I was looking for.

Brett.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,466
Latest member
DrusillaYa

Latest Threads

Top