# Sort numbers in a ragged list

Given a ragged list, e.g.

[[4, 7], [5, 3, [], [6, [2]]]]


Your challenge is to sort only the numbers in it. For example, with the above, the result would be

[[2, 3], [4, 5, [], [6, [7]]]]


The shape of the output should remain the same, only the numeric contents should change.

This is , shortest code wins!

All numbers will be unique positive integers. You may do input / output with strings.

## Testcases

[2, [3, [1, []]]] -> [1, [2, [3, []]]]
[6, 5, [[9]], 7] -> [5, 6, [[7]], 9]
[12, [43, 51], [[23, 4], 9, [22, []]]] -> [4, [9, 12], [[22, 23], 43, [51, []]]]
[9, 4, 2] -> [2, 4, 9]

• May we take input and leave output as a string or should it be a native list type? Mar 14 at 8:45
• @chunes Allowing I/O as a string seems reasonable. Mar 14 at 8:46

# Jelly, 3 bytes

FṢṁ


Try it online!

## How it works

FṢṁ - Main link. Takes a ragged list R on the left
F   - Flatten R
Ṣ  - Sort the flattened R
ṁ - Mold the sorted flattened R into the same shape as R

– Lynn
Mar 15 at 12:37
• @Lynn FGITW effect, I'm guessing. Plus the answer was posted just before the question hit HNQ :/ Mar 15 at 17:15
• @Lynn Different people value different aspects of answers. Sure Jelly makes it easy for this particular task (due to its built-in mold), but it's still a 3-bytes answer to a Code Golf question, so I personally think it deserves recognition -- if only to put Jelly in a prominent place. Mar 16 at 15:03
• Any language with a "reshape" function (including R) makes the challenge kind of trivial
– qwr
Mar 17 at 3:46

# Ruby, 51 47 bytes

->l{eval"#{l}".gsub(/\d+/,'%d')%l.flatten.sort}


Try it online!

-4 bytes thanks to Sisyphus

• This is really clever. Mar 14 at 16:48
• 47 bytes: Try it online! Mar 15 at 22:17

# R, 29 bytes

\(l)relist(sort(unlist(l)),l)

Attempt This Online!

• I think you can go even shorter using rapply!
– JDL
Mar 16 at 9:38
• @JDL I'm curious what do you have in mind, as I'm not very experienced with rapply? Mar 16 at 14:38
• \(L)rapply(L,sort,,,"l") --- actuallly rereading the question, I misunderstood it the first time so this doesn't quite do what is asked. I got so excited thinking finally rapply would have a use in code golf, "when you have a hammer, everything looks like a nail"
– JDL
Mar 16 at 16:42
• @JDL Right, not exactly what OP was looking for. Seems like we need to keep searching for a use of this function in code golf... Mar 16 at 17:35

# Wolfram Language (Mathematica), 34 bytes

0#/.(i=0):>Sort[Flatten@#][[++i]]&


Try it online!

Also works if input numbers are not unique.

0#                                  numbers become 0
/.   0 :>                         replace 0s (in order) with:
(i= )  Sort[Flatten@#][[++i]]     the corresponding sorted value


# Wolfram Language (Mathematica), 32 bytes

-2 bytes thanks to @att.

#/.Thread[#->Sort@#&@Flatten@#]&


Try it online!

• 33 bytes
– att
Mar 14 at 7:32
• 32 bytes
– att
Mar 17 at 17:10

# Retina, 5 bytes

N\d+


Try it online.

Explanation:

Sorts all numbers of 1 or more digits in the input in numerical order, and leaves every other character unchanged (including their positions).

# JavaScript (Node.js), 62 bytes

n=>n.replace(r=/\d+/g,_=>n.match(r).sort((a,b)=>a-b)[i++],i=0)


Try it online!

Probably defeats the purpose of the challenge, but it is valid. Takes in a stringified list and outputs a stringified list. Replaces the i-th number (via string replacement) with the i-th element of the list of sorted numbers.

# 05AB1E, 19 bytes

"DdiI˜{¾è¼ë®δ.V"©.V


Unfortunately, a simple flatten and replace/transliterate doesn't work on nested lists apparently. So instead, the default recursive approach I've used in multiple other challenges have been used.

Explanation:

"..."     # Create the recursive string explained below
©    # Store it in variable ® (without popping)
.V  # Evaluate and execute it as 05AB1E code
# (after which the result is output implicitly)

D         # Duplicate the current item
# (which will be the implicit input-list in the first iteration)
di       # If it's a (non-negative) integer:
I      #  Push the input-list
˜     #  Flatten it
{    #  Sort it
¾è  #  Get the ¾'th value of this sorted list
¼ #  Then increase ¾ by 1
ë       # Else (it's a list instead):
δ     #  Map over each inner list:
® .V   #   Do a recursive call for each


# Python 3.8 (pre-release), 89 bytes

def f(L):a=re.split('(\d+)',L);a[1::2]=sorted(a[1::2],key=int);return''.join(a)
import re


Try it online!

I/O are strings.

## How

This simply ignores the nesting by picking out groups of digits sorting them and putting them back into the gaps.

# APL(Dyalog Unicode), 19 bytes SBCS

∊{a⊣(∊a)←⍺[⍋∊a←⍵]}⊢


Try it on APLgolf!

A tacit function which takes a ragged array.

# Explanation

∊{a⊣(∊a)←⍺[⍋∊a←⍵]}⊢ Pass in:
⊢ The input as is on the right
∊                   The flattened input on the left.
{a⊣(∊a)←⍺[⍋∊a←⍵]}  and do the following:
a←⍵     assign right arg to 'a'
⍺[⍋∊   ]   sort the flattened input
(∊a)←           assign this result to 'a', preserving structure
a⊣                return modified 'a'

• Very good 1! I think I quite understand what's going on but an explanation would be appreciated Mar 14 at 17:34
• added an explanation Mar 15 at 11:02

# Factor + sorting.human, 93 bytes

[ find-numbers [ string? ] partition natural-sort [ present ] map 2array round-robin ""join ]


Try it online!

## Explanation

                       ! "[6,5,[[9]],7]"
find-numbers           ! { "[" 6 "," 5 ",[[" 9 "]]," 7 "]" }
[ string? ] partition  ! { "[" "," ",[[" "]]," "]" } { 6 5 9 7 }
natural-sort           ! { "[" "," ",[[" "]]," "]" } { 5 6 7 9 }
[ present ] map        ! { "[" "," ",[[" "]]," "]" } { "5" "6" "7" "9" }
2array                 ! { { "[" "," ",[[" "]]," "]" } { "5" "6" "7" "9" } }
round-robin            ! { "[" "5" "," "6" ",[[" "7" "]]," "9" "]" }
""join                 ! "[5,6,[[7]],9]"


Here's a slightly longer version that works on native sequences:

[ [ flatten natural-sort ] keep 0 -rot [ dup real? [ drop 2dup nth [ 1 + ] 2dip ] when ] deep-map ]


# Perl 5-p, 37 bytes

@a=sort{$a-$b}/\d+/g;s/\d+/shift@a/ge


Try it online!

• 35 bytes: Try it online! Mar 15 at 22:20

# Vyxal, 38 bytes

1N→_a\d+?λ←_a1+→_a\d+?Ẏ⌊s←_a iS;øṙ


Try it Online!

Thanks @lyxal for helping me a lot in chat. I've never posted any Vyxal answers before.

This is a port of my JavaScript solution. Takes a stringified list (provided with backticks around a Python-like list syntax).

• You can replace one variable with the register (£ to get and ¥ to set) and the other with the ghost variable, which has no name (Just ← and →) but is global. Also, 1N is u and 1+ is ›. Mar 15 at 19:08

# PARI/GP, 88 bytes

a->i=#l=[];t(b->l=setunion([b],l),a);t(b->l[i++],a)
t(g,a)=if(a'===0,g(a),[t(g,b)|b<-a])

Attempt This Online!

## Explanation

Here is a helper function to traverse a ragged-list, since we need to traverse the input twice:

t(g,a)=if(a'===0,g(a),[t(g,b)|b<-a])


t(g,a) traverses the ragged-list a and replaces each number in it with g(a).

Here I use an interesting trick to check if a is a list or a number: a'===0. Here a' takes the derivative of a, which is 0 if and only if a is a number.

When a is number, the function simply returns g(a). When a is a list, it returns a list of t(g,b), where b runs through a.

Now look at the main function:

a->i=#l=[];t(b->l=setunion([b],l),a);t(b->l[i++],a)


This is an anonymous function with argument a.

First it initializes l to [], i to #l (the length of l, which is 0).

Now it can do the first traversal: t(b->l=setunion([b],l),a). For each number b in the list, it set l to the union of [b] and l. PARI/GP doesn't have a separated type for sets. A set is just a sorted list without duplicate elements.

Then it does the second traversal: t(b->l[i++],a). For each number b in the list, it increments i, and replaces b with the i'th element in l`. This gives the final result.