Indentation-based Sort
Python 2, 117 bytes
lambda S:[s[-1]for s in sorted(reduce(lambda t,s:t+[[v for v in t[-1]if v.count(' ')<s.count(' ')]+[s]],S,[[]]))[1:]]
Try it online!
Takes as input a list of strings; and outputs a list of strings, sorted as required.
The idea is to turn each element into a list which contains the "absolute path" as a list; and then let Python handle the sorting. E.g. if the input is:
[
'a',
' c',
' d',
' b'
]
Then via the reduce()
, we convert to a list of lists:
[
['a'],
['a',' c'],
['a',' c', ' d'],
['a',' b']
]
which gets sorted as:
[
['a'],
['a',' b']
['a',' c'],
['a',' c', ' d'],
]
and then output the last element of each list in the list-of-lists to get:
[
'a',
' b'
' c',
' d',
]
APL (Dyalog Unicode), 31 bytesSBCS
Anonymous prefix lambda, takes and returns list of strings.
{⍵[⍋{1=≢⍵:⍺⋄⍵}⍀↑' '(,⊂⍨⊣=,)¨⍵]}
Try it online!
{
…}
"dfn"; ⍵
is argument
⍵[
…]
index the argument with the following indices:
' '(
…)¨⍵
apply the following tacit function to each string with space as left argument:
,
concatenate the space to the string
⊣=
Boolean list indicating where the space is equal to each character that
,⊂⍨
use that to partition (begin part where true) the concatenation of space and string
↑
mix list of lists of strings into matrix of strings
{
…}⍀
vertical cumulative reduction by this "dfn"; ⍺
and ⍵
are upper and lower args:
≢⍵
the length of the lower string
1=
is that equal to 1? (i.e. is there nothing but the single space there?)
:⍺
if so, return the upper argument
⋄⍵
else, return the lower argument
⍋
grade up (find indices which will sort that)
Retina, 47 bytes
+-1m`(?<=^\2(\S+).*?¶( *))
$1
O$`
$L$&
\S+
Try it online! Note: Several lines have trailing spaces. Explanation:
+-1m`(?<=^\2(\S+).*?¶( *))
$1
The first step is to insert each word into following lines at the same indentation. For example, with the lines aisle
, wasabi
and elf
the resulting lines are aisle
, aisle wasabi
and aisle wasabi elf
. I discovered this regex by trial and error so there may be edge cases with it.
O$`
$L$&
We can now sort the lines case-insensitively.
\S+
Delete all of the inserted words.