Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort an array of age ranges with both numbers and characters?

I have an array of strings that represent age ranges:

$AgeRanges = ( 
"<1",
"1-4",
"5-9",
"10-14",
"15-19",
"20-24",
"25-29",
"30-34",
"35-39",
"40-44",
"45-49",
"50+"
)

And if I sort them with Sort-Object I will get:

$AgeRanges | Sort-Object
<1
10-14
1-4
15-19
20-24
25-29
30-34
35-39
40-44
45-49
50+
5-9

After trying to split the strings and then convert them to integers and sort them that way and then reconstituting them with the string characters and converting them back to strings, I gave up and just hard coded the list into my script. But I have other such list that deal with children and babies.

Is there any elegant way to handle this type of problem that I am missing? Prompt the user to supply the age ranges? Shuffle the array around in fixed manner?

like image 442
Dr. Sicoco Avatar asked Dec 12 '25 00:12

Dr. Sicoco


2 Answers

You can pass a calculated property expression to Sort-Object and have it sort based on some derived value - like the first set of digits!

$AgeRanges |Sort-Object {$_-notlike'<*'},{($_-replace '^.*?(\d+).*$','$1') -as [int]}

The first expression will sort the input into 2 groups - those starting with < go before the rest - this ensures the lower open range (<1) always goes first.

The regex pattern ^.*?(\d+).*$ will match the entire string, capturing the first consecutive sequence of digits ((\d+)), and then replacing the whole thing with just that - ie. <1 becomes 1, 15-19 becomes 15, etc.

The conversion to [int] will force Sort-Object to sort by ordinal numeric value rather than alphabetical, so you get 5-9 before 45-49 and so on.

like image 191
Mathias R. Jessen Avatar answered Dec 14 '25 08:12

Mathias R. Jessen


The only items that need to be changed for proper lexicographical sorting are 1-4 and 5-9, adding a 0 before each digit (01-04 and 05-09) would make the collection be properly sorted so:

$AgeRanges = (
    '<1',
    '1-4',
    '5-9',
    '10-14',
    '15-19',
    '20-24',
    '25-29',
    '30-34',
    '35-39',
    '40-44',
    '45-49',
    '50+'
) | Sort-Object { Get-Random } # sort randomly for testing

$AgeRanges | Sort-Object { $_ -replace '^\d(?=-)|(?<=-)\d$', '0$0' }

See https://regex101.com/r/Xuzeaj/1 for regex details.

like image 20
Santiago Squarzon Avatar answered Dec 14 '25 09:12

Santiago Squarzon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!