# Sorting interview question

I have been busy with my new position, so I haven't been able to put as much time and thought into my blog posts.

I have question that was asked of me on my job interview:

You have an array of items, each element matches the following pattern:
/^[a-zA-Z]+[0-9]+\$/
You want to sort the array both alphabetically and numerically:

ie 'abc123' comes after 'abc2' because 2<123 when compared numerically.

How would you do this?

Can you do it in one line code? Mine wasn't but I still got the job, However I have seen it in one line of code.

```my @sorted = map  { \$_->[0] }
sort { \$a->[2] cmp \$b->[2] }
sort { \$a->[3]  \$b->[3] }
map  {[\$_, split(/^([a-zA-Z]+)([0-9]+)/) ] } @list;
```

Just a stab at it. My limited test seemed to work.

Brain's tired so I haven't thought about why the second index is empty...maybe I'll think about it tomorrow...or not.

I suspect someone could golf this, but:

my @sorted = sort { ( (\$a, \$b) =~ s/\d*// && \$a cmp \$b ) || ( (\$a, \$b) =~ s/[^\d]*// && \$a <=> \$b) } @unsorted;

I tested this with the following one-liner:

\$perl -E'say for sort { ( (\$a, \$b) =~ s/\d*// && \$a cmp \$b ) || ( (\$a, \$b) =~ s/[^\d]*// && \$a <=> \$b) } @ARGV' -- abc123 abc2 aa1 az0 aa2
aa1
aa2
abc123
abc2
az0

my oneliner:

sort { sub { \$_[0] cmp \$_[2] or \$_[1] <=> \$_[3] }->( map /^([a-zA-Z]+)([0-9]+)\$/,(\$a,\$b) ) } @arr;

Chris Prather, your example in not so right

(\$a,\$b) =~ s/// works like \$b =~ s///

and i found THE BEST SOLUTION for this question:

sort { \$a cmp \$b or \$a <=> \$b } @unsorted

TA DA!!!!

```use Sort::Naturally qw(nsort);
nsort @list;
```

You can join that to a single line if you feel like...

> and i found THE BEST SOLUTION for this question:
> sort { \$a cmp \$b or \$a \$b } @unsorted
> TA DA!!!!

I was wrong, \$a \$b never happens.

Right values to test is 'a1' and 'a02'

I think this just is all sorts of win (no pun intended).

Okay so lemme update a bit, this combines basically everything people have had. It's longer than the sort { sub {...}->(map // \$a,\$b) } but I think a bit clearer.

```
@sorted =
map { local \$"; "@\$_" }
sort { \$\$a[0] cmp \$\$b[0] or \$\$a[1] <=> \$b[1] }
map { [/(\w+)(\d+)/] }
@unsorted;
```

Or in one-liner for the command line

\$perl -E'say for map { local \$"; "@\$_" } sort { \$\$a[0] cmp \$\$b[0] or \$\$a[1] <=> \$\$b[1] } map { [/(\w+)(\d+)/] } @ARGV' -- a13 aa03 a1 aa2 a02
a1
a02
a13
aa2
aa03

I like the Sort::Natural solution best though :)