Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

how to sort this?

by sen (Hermit)
on Mar 25, 2006 at 05:20 UTC ( #539144=perlquestion: print w/replies, xml ) Need Help??
sen has asked for the wisdom of the Perl Monks concerning the following question:

Greetings monks.

I have a problem in sorting a array. If array contains both digits & characters. my array is like

@a = qw/1x1 1x12 12x3 10x1 4x12 4x1 1x1 22x3 2x1 4x0 12x1 1x2/;

Is there any way to sort this.

Thanks in advance

Replies are listed 'Best First'.
Re: how to sort this?
by ikegami (Pope) on Mar 25, 2006 at 05:41 UTC

    The following sorts numerically by the number preceeding the 'x', then numerically by the number following the 'x':

    @a = sort { my ($a1, $a2) = split(/x/, $a); my ($b1, $b2) = split(/x/, $b); $a1 <=> $b1 || $a2 <=> $b2 } @a;

      The OP said the elements contain "both digits & characters", which I assume means (one or more digits) followed by (one or more alpha chars) followed by (one or more digits). If that's the case, ikegami's sort routine can be generalized to include the alpha component:

      @a = sort { my ($a1, $a2, $a3) = ( $a =~ m/(\d+)(\D+)(\d+)/ ); my ($b1, $b2, $b3) = ( $b =~ m/(\d+)(\D+)(\d+)/ ); $a1 <=> $b1 || $a2 cmp $b2 || $a3 <=> $b3 } @a;

      The OP wasn't clear about the specifics, though. If there really is just a single 'x' between the digit portions (and it's always an 'x'), the generalization isn't needed. If by "characters" the OP meant "any character" (as opposed to only alpha chars), then things get more complex.

Re: how to sort this?
by johngg (Abbot) on Mar 25, 2006 at 12:09 UTC
    An alternative for those who like Schwartzian Transforms.

    @a = map {$_->[0]} sort {$a->[1] <=> $b->[1] || $a->[2] <=> $b->[2]} map {[$_, split /x/]} @a;



Re: how to sort this?
by saintmike (Vicar) on Mar 25, 2006 at 05:48 UTC
    What do you want to sort it by? Sort it like strings? Like numbers? By extracted integers? Or a combination of all of the above?

    Helps to know the requirements before starting an implementation.

      hi saint,

      my requirement is to sort by integers. also i need the output as

      @a = (1x1 1x1 1x2 1x12 2x1 4x0 4x1 4x12 10x1 12x1 12x3 22x3);


        Hi sen try this it gives your exact output,

        #!/usr/local/bin/perl @a1 = qw/1x1 1x12 12x3 10x1 4x12 4x1 1x1 22x3 2x1 4x0 12x1 1x2/; @out = sort { (split 'x', $a, 2)[0] <=> (split 'x', $b, 2)[0] } sort { (split 'x', $a, 2)[1] <=> (split 'x', $b, 2)[1] }@a1; print "@out";
Re: how to sort this?
by salva (Abbot) on Mar 25, 2006 at 11:19 UTC
    use Sort::Key::Maker iikeysort => qw(integer integer); @sorted = iikeysort { /^(\d+)x(\d+)$/ } @a;
    update: and now even simpler:
    use Sort::Key::Multi 'iikeysort'; @sorted = iikeysort { /^(\d+)x(\d+)$/ } @a;
    or if the chars between the two numbers can vary:
    use Sort::Key::Multi 'isikeysort'; @sorted = isikeysort { /^(\d+)(\w+)(\d+)$/ } @a;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://539144]
Approved by ikegami
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2017-01-21 00:35 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (180 votes). Check out past polls.