Re: sorting number
by GrandFather (Saint) on Apr 09, 2019 at 06:44 UTC
|
A fairly standard approach is to break the identifier up into a letter part and a number part, sort by each as needed, then join the bits back together again. There is a Perl idiom that makes that fairly easy and clean to do:
use strict;
use warnings;
my @rawList = qw(
CORE1
COREA11
CORE12
COREA130
CORE8
CORE233
COREA12
COREA115
);
my @sortedList =
# Join letter and number parts back together
map{$_->[0] . $_->[1]}
# sort first by letter part, then if that is equal sort by number
+part
sort {$a->[0] cmp $b->[0] || $a->[1] <=> $b->[1]}
# Use a regex to split each item into a letter part and a number p
+art
map{[/([^\d]+)([\d]+)/]} @rawList;
print join "\n", @sortedList;
Prints:
CORE1
CORE8
CORE12
CORE233
COREA11
COREA12
COREA115
COREA130
Note that map takes a list, processes each element, and returns a new list. The expression executes its main parts essentially from right to left: the last map executes first, then the sort, then finally the first map.
Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
| [reply] [d/l] [select] |
Re: sorting number
by NetWallah (Canon) on Apr 09, 2019 at 04:38 UTC
|
Read the sort function documentation.
The relevant parts are:
* <=> does NUMERIC comparison.
* cmp does text/string comparison
You also need to extract the numeric part from the string when you want a numeric sort.
Regular expressions are useful for that.
"It's ten o'clock... Do you know where your AI programs are?"
| [reply] |
|
Thanks replay, yes I know each function. but I want to use both of them. Is it possible to use both of them?
| [reply] |
Re: sorting number
by haukex (Archbishop) on Apr 09, 2019 at 07:47 UTC
|
| [reply] |
Re: sorting number
by Tux (Canon) on Apr 09, 2019 at 06:22 UTC
|
my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map {
[ $_, s/^CORE//r =~ s/(\d+)/sprintf "%06d", $1/ger ] } @aa;
Enjoy, Have FUN! H.Merijn
| [reply] [d/l] |
|
c:\@Work\Perl\monks>perl -wMstrict -le
"my @aa = qw(
CORE1 CORE12 CORE8 CORE233 COREA11 COREA12 COREA130 COREA115
);
my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map {
[ $_, s/(\d+)/sprintf \"%06d\", $1/ger ] } @aa;
print qq{@sorted};
"
CORE1 CORE8 CORE12 CORE233 COREA11 COREA12 COREA115 COREA130
Can you please elaborate?
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
Re: sorting number
by AnomalousMonk (Archbishop) on Apr 09, 2019 at 07:01 UTC
|
# I want to print CORE1 CORE12 CORE233 CORE8 COREA11 COREA12 COREA115 COREA130
This is not the ordering produced by either Tux's solution or by GrandFather's solution (both of which produce the same ordering), and I don't understand what you want | the internal logic of the ordering you have specified. Can you please clarify?
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re: sorting number
by johngg (Canon) on Apr 09, 2019 at 10:03 UTC
|
Yes, the problem description and desired output do not seem to match. Anyway, here's a GRT for sorting letters then numbers, casting non-compliant lines to the top of the output.
use 5.026;
use warnings;
my @aa = qw{
CORE1
CORE12
CORE8
duffdata
CORE233
COREA11
COREA12
COREA130
COREA12b
COREA115
};
say for
map { substr $_, 54 }
sort
map {
my( $letters, $digits ) =
m{^([A-Za-z]+)(\d+)$}
? ( $1, $2 )
: ( q{}, 0 );
pack q{A50NA*}, $letters, $digits, $_;
} @aa;
The output.
COREA12b
duffdata
CORE1
CORE8
CORE12
CORE233
COREA11
COREA12
COREA115
COREA130
I hope this is of interest.
| [reply] [d/l] [select] |
Re: sorting number
by kcott (Archbishop) on Apr 09, 2019 at 07:47 UTC
|
G'day dideod.yang,
What you have as "I want to print ..." is not really sorted.
Perhaps you wrote COREA12 and COREA115 around the wrong way.
If that's the case, you'd need to split each element into alphabetic and numeric parts
but do a string comparison on both of them:
$ perl -E '
say map "$_->[0]$_->[1] ",
sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] }
map [/(\D+)(\d+)/], qw{
CORE1 CORE12 CORE8 CORE233
COREA11 COREA12 COREA130 COREA115
}
'
CORE1 CORE12 CORE233 CORE8 COREA11 COREA115 COREA12 COREA130
| [reply] [d/l] [select] |
|
My guess is that it was the CORE8 that was misplaced, and GrandFather's and Tux's solutions are the expected output.
I suppose you meant to write <=> on the right side? Otherwise your code gives the same output as a plain sort
| [reply] [d/l] |
|
"My guess is that it was the CORE8 that was misplaced, ..."
Quite possibly - it's all guesswork. :-)
"I suppose you meant to write <=> on the right side?"
No, cmp was intended.
I was aiming to indicate that cmp would give "11 115 12 130";
whereas <=> would give "11 12 115 130".
It would appear I failed to communicate my intent.
Thanks for pointing this out and giving me the opportunity to provide clarification.
| [reply] [d/l] [select] |
|
c:\@Work\Perl\monks>perl -wMstrict -le
"my @sorted =
sort
qw(CORE1 CORE12 CORE8 CORE233 COREA11 COREA12 COREA130 COREA115)
;
print qq{@sorted};
"
CORE1 CORE12 CORE233 CORE8 COREA11 COREA115 COREA12 COREA130
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
| [reply] |
Re: sorting number
by kcott (Archbishop) on Apr 10, 2019 at 07:51 UTC
|
I've front-paged this.
This is not reflection of the OP which, as many have pointed out, leaves a lot to be desired.
It is a reflection of the excellent responses:
when checking Best Nodes of the Day after work today, 7 of the top 10 were from this thread.
| [reply] |
Re: sorting number
by Marshall (Canon) on Apr 10, 2019 at 03:23 UTC
|
It would help the Monks greatly if the spec was more clear.
# I want to print CORE1 CORE12 CORE233 CORE8 COREA11 COREA12 COREA115
An alpha sort order will get 1,12,233,8 for CORE
A numeric sort order will get 11,12,115 for COREA
But a single general sort routine cannot do both.
At a minimum you have to specify more rules about how to reach your desired output.
There are many ways to code sorts in Perl. Some of them are quite clever and faster for large sorts versus a more straightforward approach. I personally start thinking about these fancy things when the array is >1,000 or in situations where the code is going to be run very often, by that I mean more than once per second. | [reply] |