4
\$\begingroup\$

Given a list of n strings, return a list of that strings in ascending order. However, be aware, that in this case we want integer comparison for all numbers appearing in the strings, meaning that "12" > "3".

Example cases:

{"abc123", "abc6", "abc47", "abd49"} -> {"abc6", "abc47", "abc123", "abd49"}
{"foo0", "bar12", "foobar12", "foo"} -> { "bar12", "foo", "foo0", "foobar12"}
{"Bond007", "Bond07", "Bond7", "Bond12"} -> {"Bond007", "Bond07", "Bond7", "Bond12"}
{"one1", "one11two23", "one1two2", "one1two3", "1"} -> {"1", "one1", "one1two2", "one1two3", "one11two23"}

You can expect to only find [a-zA-Z0-9]+ in each string. This is so shortest code in bytes wins. Standard Loopholes are forbidden.

Update:
- Sorting is case insensitive
- The ascending order is integers < "abcdefghijklmnopqrstuvwxyz"
- Every sequence of integers as in the aforementioned order should be interpreted as one integer, meaning "421" represents 421, not 4, 2 and 1 and thus is smaller than "1341", as 421 < 1341

-Treat numbers with leadings zeroes as though they were decimals meaning "001" -> "0.01" so "001" < "01" < "1"

Thanks for Adám for pointing out, that this is called natural sort order.

\$\endgroup\$

closed as unclear what you're asking by user202729, Pavel, Οurous, Jo King, Ørjan Johansen Feb 22 '18 at 3:33

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    \$\begingroup\$ Unfortunately, there are a lot specifications missing here. \$\endgroup\$ – Adám Feb 22 '18 at 1:53
  • 4
    \$\begingroup\$ Also, it's still unclear what to do about 01 vs. 010. \$\endgroup\$ – Ørjan Johansen Feb 22 '18 at 3:38
  • 4
    \$\begingroup\$ The decimals' rule doesn't make any sense. I think what you want is that otherwise identical numbers, but where some have leading zeros, should sort by length, longest first, right? \$\endgroup\$ – Adám Feb 22 '18 at 7:49
  • 4
    \$\begingroup\$ Since the case insensitivity leads to ties you have to specify if the sort has to be stable or not. I suggest not since otherwise you force people whose language sort is unstable to implement their own sort \$\endgroup\$ – Ton Hospel Feb 22 '18 at 8:42
  • 3
    \$\begingroup\$ This is a nice challenge I'd like to do but the spec is still incomplete. So could you please update your question ? The only things you still need to do is to specify how ties in the sorting are to be handled and fix the rule for leading zeros (presumably saying that more leading zeros sort before less leading zeros instead of trying to get to this using fractions). \$\endgroup\$ – Ton Hospel Feb 27 '18 at 8:53
1
\$\begingroup\$

Python 2, 68 bytes

lambda l:sorted(l,key=lambda x:int(re.sub("\D","",x)or 0))
import re

Try it online!

I used something like this to sort PDF files recently!

my entry originally didn't work but Neil fixed it (thanks!)

\$\endgroup\$
1
\$\begingroup\$

Perl 6,  32 31  30 bytes

*.sort(*.comb(/\d+|\D+/)».&val)

Test it

*.sort(*.comb(/\d+|\D/)».&val)

Test it

*.sort(*.comb(/\d+|./)».&val)

Test it

Expanded:

*\                         # WhateverCode lambda (this is the parameter)

.sort(                     # sort by doing the following to each string

  *.comb( / \d+ | . / )\ # split the string into consecutive digits or a character

  ».&val                   # convert each to a Numeric if possible

)

Note:

"Bond007".comb(/\d+|\D+/)».&val
# results in
("Bond", IntStr.new(7, "007"))

# and

"Bond007".comb(/\d+|./)».&val
# results in
("B", "o", "n", "d", IntStr.new(7, "007"))
\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog Unicode) 17.0 (currently in alpha), 31 bytesSBCS

Anonymous tacit prefix function taking a list of strings as argument.

⊂⊃¨⍨∘⍋({0::⍵⋄⍎⍵}¨⊢⊂⍨1,2≠/∊∘⎕D)¨

As version 17.0 isn't on TIO yet, here is a test session transcript:

      f←⊂⊃¨⍨∘⍋({0::⍵⋄⍎⍵}¨⊢⊂⍨1,2≠/∊∘⎕D)¨
      ⎕JSON f ⎕JSON '["abc123", "abc6", "abc47", "abd49"]'
["abc6","abc47","abc123","abd49"]
      ⎕JSON f ⎕JSON '["foo0", "bar12", "foobar12", "foo"]'
["bar12","foo","foo0","foobar12"]
      ⎕JSON f ⎕JSON '["Bond007", "Bond07", "Bond7", "Bond12"]'
["Bond007","Bond07","Bond7","Bond12"]
      ⎕JSON f ⎕JSON '["one1", "one11two23", "one1two2", "one1two3", "1"]'
["1","one1","one1two2","one1two3","one11two23"]

 from the entire argument…

⊃¨⍨ pick each of the indices…

 that are…

 the ascending grade (indices which would place in ascending order) of…

( the following tacit function applied to each of the strings:

∊∘⎕D Boolean mask for the characters which are members of the set of Digits

2≠/ pairwise inequality of that (i.e. indicate beginnings of letter runs and digit runs)

1, prepend 1 to mark the first character as beginning a run

⊢⊂⍨ use that to partition (beginning partitions at 1s) the string

{ apply the following anonymous lambda to each partition:

  0:: if any error happens, then:
    return the argument as-is

   try to:
   ⍎⍵ evaluate the argument

\$\endgroup\$
0
\$\begingroup\$

Python 3, 107 106 bytes

import re
lambda a:sorted(a,key=lambda x:[n.isdigit()and n.zfill(9)or n for n in re.findall('\d+|\D+',x)])

Try it online!

Abused the fact that Python compares two lists lexicographically. Unfortunately re.split(r'\b',x) does not work.

\$\endgroup\$
  • \$\begingroup\$ r'... -> '.... \$\endgroup\$ – Jonathan Frech Feb 22 '18 at 1:48
  • \$\begingroup\$ Thanks, I didn't know that works. \$\endgroup\$ – Bubbler Feb 22 '18 at 1:50
0
\$\begingroup\$

Python 2, 92 bytes

lambda q:map(lambda a:a[1],sorted(map(lambda a:[int(re.sub("\D","",a)or 0),a],q)))
import re

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 3, 125 bytes

lambda a:[y for _,y in sorted([([i%2and int(e)or e for i,e in enumerate(re.findall("(\D+|\d+)",s))],s)for s in a])]
import re

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Seems to ignore zeros. \$\endgroup\$ – Jonathan Frech Feb 22 '18 at 1:47
  • \$\begingroup\$ @JonathanFrech Thanks, fixed for -11 bytes \$\endgroup\$ – HyperNeutrino Feb 22 '18 at 2:11
0
\$\begingroup\$

Jelly, 9 bytes

fØD$V$,$Þ

Try it online!

Explanation

fØD$V$,$Þ  Main Link
        Þ  Sort with key:
fØD        Filter to keep only digits
    V      Jelly-eval the result
      ,    Pair with original string (for tiebreak)
   $ $ $   (Link combiners, syntax thing)

Idea taken from linemade's Python solution. Footer is purely for formatting.

\$\endgroup\$
0
\$\begingroup\$

05AB1E, 7 bytes

ΣDþïs)}

Try it online!

Explanation

ΣDþïs)}  Full Program
Σ     }  Sort by result of key: a
 D       a, a
  þ      digits_only(a), a
   ï     int(digits_only(a)), a
    s    a, int(digits_only(a))
     )   [a, int(digits_only(a))]
\$\endgroup\$
  • \$\begingroup\$ @Adám Fixed, thanks \$\endgroup\$ – HyperNeutrino Feb 22 '18 at 2:43
0
\$\begingroup\$

PHP 7, 17 bytes

<?php natsort()?>

natsort"Sort an array using a 'natural order' algorithm"

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.