Sorting array of hash references

A

alwaysonnet

hi all,

I've got an array of hash-references as following. ( i've represented
hash-references as a table below)


Type A/C No Status(active/inactive)

Prefund 12345 Y
Prefund 45678 N
Receipt 78878 N
Receipt 32365 Y
Payment 56546 N
Payment 23456 N
Payment 34093 Y

I want to display all the active accounts (status with "Y") before
inactive accounts along with preserving the order by type ie., Prefund
should come first before Receipt and Payment along the order.

I've got the code which i've hard-coded the account type(Payment) and
then sorting according to their status.

foreach my $label(@accts) {
if ($label->{'batype'} eq "Payment") {
push(@acct_pay,$label);
}
}
foreach $x(@acct_pay) {
@sorted = sort { $b->{'baactive'} cmp $a->{'baactive'} } @acct_pay;
}

Is there any way of how to achieve this by sorting according to status
by preserving the account type order.

Thanks a ton,
Raj
 
A

anno4000

alwaysonnet said:
hi all,

I've got an array of hash-references as following. ( i've represented
hash-references as a table below)

It would have been *much* better to present Perl code that produces
the array of hashes instead of a table that leaves us guessing how
your data relate to your code.
Type A/C No Status(active/inactive)

Prefund 12345 Y
Prefund 45678 N
Receipt 78878 N
Receipt 32365 Y
Payment 56546 N
Payment 23456 N
Payment 34093 Y

I want to display all the active accounts (status with "Y") before
inactive accounts along with preserving the order by type ie., Prefund
should come first before Receipt and Payment along the order.

Unless you're running a rather old version of Perl, Perl's sort() is
stable, meaning the original order is preserved when elements compare
equal. If you simply sort by status the result should be what you
want.
I've got the code which i've hard-coded the account type(Payment) and
then sorting according to their status.

foreach my $label(@accts) {
if ($label->{'batype'} eq "Payment") {

Is "batype" what appears in the column "Type"? Is "baactive" what
appears in column "Status(active/inactive)"? Please make explicit
what is what, don't let your readers guess.
push(@acct_pay,$label);
}
}
foreach $x(@acct_pay) {
@sorted = sort { $b->{'baactive'} cmp $a->{'baactive'} } @acct_pay;
}

Is there any way of how to achieve this by sorting according to status
by preserving the account type order.

That will only show the three "Payment" records. What does it have to
do with your question?

Anno
 
A

alwaysonnet

hi ,

"batype" refers to column "Type" , "baactive" refers to column
"Status(active/inactive)"?

anno, You're correct that the code will show only 3 records of
"Payment" type as I have put a condition like "if ($label->{'batype'}
eq "Payment") ".

I need to preserve the actual order of "Type" but for each "Type" i
need to sort with their active accounts.

Raj
 
A

anno4000

alwaysonnet said:
hi ,

"batype" refers to column "Type" , "baactive" refers to column
"Status(active/inactive)"?

anno, You're correct that the code will show only 3 records of
"Payment" type as I have put a condition like "if ($label->{'batype'}
eq "Payment") ".

I need to preserve the actual order of "Type" but for each "Type" i
need to sort with their active accounts.

[Tofu snipped. Don't do that]

So just sort by "baactive", your records are already sorted by "batype".
As I said in my previous reply, Perl's sort is stable unless you have
an old version of Perl.

Anno
 
T

Tad McClellan

I've got an array of hash-references as following.


If you say so, but those are some mighty cumbersome keys...

( i've represented
hash-references as a table below)


Why have you done that rather than representing them in real Perl
code that an answerer could use to test any potential answers?

If you make the answerer do that extra work, they are likely to move on
to helping some other poster who has taken the time to make it
easier for them to give an accurate answer.

Have you seen the Posting Guidelines that are posted here frequently?


[ snip the table ]

I want to display all the active accounts (status with "Y") before
inactive accounts along with preserving the order by type ie., Prefund ^^^^^^^^^^^^^^^^^^^^
should come first before Receipt and Payment along the order.


Recent perls have a "stable" sort, so you should get that by default.

if ($label->{'batype'} eq "Payment") {
^^^^^^

That is not the key that you said in the table. Which is it?

Precision is important in programming...

Is there any way of how to achieve this by sorting according to status
by preserving the account type order.


Yes, and it is a plain old everyday sort that you should have been
able to get simply by reading the docs about sorting...


----------------------------
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my @records = (
{ 'Type' => 'Prefund', 'A/C No' => 12345, 'Status(active/inactive)' => 'Y' },
{ 'Type' => 'Prefund', 'A/C No' => 45678, 'Status(active/inactive)' => 'N' },
{ 'Type' => 'Receipt', 'A/C No' => 78878, 'Status(active/inactive)' => 'N' },
{ 'Type' => 'Receipt', 'A/C No' => 32365, 'Status(active/inactive)' => 'Y' },
{ 'Type' => 'Payment', 'A/C No' => 56546, 'Status(active/inactive)' => 'N' },
{ 'Type' => 'Payment', 'A/C No' => 23456, 'Status(active/inactive)' => 'N' },
{ 'Type' => 'Payment', 'A/C No' => 34093, 'Status(active/inactive)' => 'Y' },
);

my @sorted = sort { $b->{'Status(active/inactive)'} cmp
$a->{'Status(active/inactive)'}
} @records;

print Dumper \@sorted;
 
X

xhoster

alwaysonnet said:
hi ,

"batype" refers to column "Type" , "baactive" refers to column
"Status(active/inactive)"?

anno, You're correct that the code will show only 3 records of
"Payment" type as I have put a condition like "if ($label->{'batype'}
eq "Payment") ".

I need to preserve the actual order of "Type" but for each "Type" i
need to sort with their active accounts.

[Tofu snipped. Don't do that]

So just sort by "baactive", your records are already sorted by "batype".
As I said in my previous reply, Perl's sort is stable unless you have
an old version of Perl.

But that isn't necessarily what he wants. Maybe He wants them sorted
first by type, then by status. Not first by status, but then by type,
which is what stable sort would give him.


my %type_order = qw/Prefund 1 Receipt 2 Payment 3/;

@sorted = sort { $type_order{$a->{'type'}} <=> $type_order{$b->{'type'}}
||
$b->{'baactive'} cmp $a->{'baactive'}
} @acct_pay;

Xho
 
A

anno4000

alwaysonnet said:
hi ,

"batype" refers to column "Type" , "baactive" refers to column
"Status(active/inactive)"?

anno, You're correct that the code will show only 3 records of
"Payment" type as I have put a condition like "if ($label->{'batype'}
eq "Payment") ".

I need to preserve the actual order of "Type" but for each "Type" i
need to sort with their active accounts.

[Tofu snipped. Don't do that]

So just sort by "baactive", your records are already sorted by "batype".
As I said in my previous reply, Perl's sort is stable unless you have
an old version of Perl.

But that isn't necessarily what he wants. Maybe He wants them sorted
first by type, then by status. Not first by status, but then by type,
which is what stable sort would give him.

I thought of that, but

I want to display all the active accounts (status with "Y") before
inactive accounts...

doesn't leave much doubt that "status" is the primary key.

[nicely formatted two-key sort snipped]

Since the primary key is only two-valued, sort() could be replaced
with two grep()s (untested):

@sorted = (
grep( $_->{ baactive} eq 'Y', @acct_pay),
grep( $_->{ baactive} eq 'N', @acct_pay),
);

Anno
 
A

alwaysonnet

hi,

my %type_order = qw/Prefund 1 Receipt 2 Payment 3/;

my @records = (
{ 'Type' => 'Prefund', 'A/C No' => 12345, 'Status(active/inactive)' =>
'Y' },
{ 'Type' => 'Prefund', 'A/C No' => 45678, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Receipt', 'A/C No' => 78878, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 88888, 'Status(active/inactive)' =>
'Y' },
{ 'Type' => 'Receipt', 'A/C No' => 32365, 'Status(active/inactive)' =>
'Y' },
{ 'Type' => 'Prefund', 'A/C No' => 11111, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 56546, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 23456, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 34093, 'Status(active/inactive)' =>
'Y' },
);

my @sorted = sort { $type_order{$a->{'Type'}} <=>
$type_order{$b->{'Type'}}
||
$b->{'Status(active/inactive)'} cmp
$a->{'Status(active/inactive)'}

} @records;

which is exactly displaying the active records for a particular account
type.

Can further sorting on 'A/C No' so that all the active/inactive records
for a particular account type should be displayed in sorted order.

Ex: In this case for the type "Prefund" a/c no's 45678 and 11111 are
not sorted where their active/inactive status are "N".

Thanks,
Raj
 
T

Tad McClellan

alwaysonnet said:
hi,

my %type_order = qw/Prefund 1 Receipt 2 Payment 3/;

my @records = (
{ 'Type' => 'Prefund', 'A/C No' => 12345, 'Status(active/inactive)' =>
'Y' },


That is a horrid choice of Status key.

Q: is the status active or inactive?

A: yes

huh??

'Status active' => 'Y'

or

'Status' => 'active'

would be much better.

{ 'Type' => 'Prefund', 'A/C No' => 45678, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Receipt', 'A/C No' => 78878, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 88888, 'Status(active/inactive)' =>
'Y' },
{ 'Type' => 'Receipt', 'A/C No' => 32365, 'Status(active/inactive)' =>
'Y' },
{ 'Type' => 'Prefund', 'A/C No' => 11111, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 56546, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 23456, 'Status(active/inactive)' =>
'N' },
{ 'Type' => 'Payment', 'A/C No' => 34093, 'Status(active/inactive)' =>
'Y' },
);

my @sorted = sort { $type_order{$a->{'Type'}} <=>
$type_order{$b->{'Type'}}
||
$b->{'Status(active/inactive)'} cmp
$a->{'Status(active/inactive)'}

} @records;

which is exactly displaying the active records for a particular account
type.

Can further sorting on 'A/C No' so that all the active/inactive records
for a particular account type should be displayed in sorted order.


Yes.

What happened when you tried it?

If you show us your broken code we will help you fix it.
 
A

alwaysonnet

Sorry if I'm putting more no of keys. This is my final requirement.

For a particular "Type", if two or more records are having the same
status and same currency then sort them according to their a/c no's
where a/c no is a unique.

Here , Data is displayed for every "Type" in sorted order of their
"ZCurrency" based on their "Status".

for ex : For "Type", Payment where A/C Status are "Y" , with a/c no's
2247,2244 ,records are displayed based on Currencies "AUS","BEL".

Similarly, for the "Type", Payment where A/C Status are "N" , with a/c
no's 56546,44444 are having the same currency "EUR".

So my requirement is that I want these two records with a/c no's
56546,44444 in sorted order.

#!/usr/bin/perl
use Data::Dumper;

my %type_order = qw/Prefund 1 Receipt 2 Payment 3/;

my @records = (
{'Type'=>'Prefund' , 'A/C No'=>12345 , 'Status active'=>'Y',
'ZCurrency' =>'GBP'},
{'Type'=>'Prefund' , 'A/C No'=>45678 , 'Status active'=>'N',
'ZCurrency' =>'SEK'},
{'Type'=>'Prefund' , 'A/C No'=>33333 , 'Status active'=>'N',
'ZCurrency' =>'ZAR'},
{'Type'=>'Receipt' , 'A/C No'=>32365 , 'Status active'=>'Y',
'ZCurrency' =>'EUR'},
{'Type'=>'Receipt' , 'A/C No'=>78878 , 'Status active'=>'N',
'ZCurrency' =>'AIR'},
{'Type'=>'Receipt' , 'A/C No'=>64237 , 'Status active'=>'N',
'ZCurrency' =>'GBP'},
{'Type'=>'Payment' , 'A/C No'=>2247 , 'Status active'=>'Y',
'ZCurrency' =>'AUS'},
{'Type'=>'Payment' , 'A/C No'=>2244 , 'Status active'=>'Y',
'ZCurrency' =>'BEL'},
{'Type'=>'Payment' , 'A/C No'=>56546 , 'Status active'=>'N',
'ZCurrency' =>'EUR'},
{'Type'=>'Payment' , 'A/C No'=>44444 , 'Status active'=>'N',
'ZCurrency' =>'EUR'},
);

my @sorted = sort { $type_order{$a->{'batype'}} <=>
$type_order{$b->{'batype'}}
||
$b->{'baactive'} cmp
$a->{'baactive'}
||
$a->{'banum'} <=> $b->{'banum'}
||
$a->{'bacur'} eq $b->{'bacur'}
} @records;

print Dumper \@sorted;

Thanks a ton.
Raj
 

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
473,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top