Вы можете использовать накопление для распространения исходного индекса родительского объекта Thing на все элементы в его группе. Затем t ie значение родителей для каждой группы и затем используйте обычную сортировку для этих кортежей, чтобы сохранить Subthings привязанными к их исходному родительскому элементу, одновременно сортируя обоих родителей между собой и дочерними элементами их родительского элемента.
Обратите внимание, что вам также нужно будет отслеживать, какой элемент является родительским, чтобы родители продолжали появляться первыми в своей группе:
things = ["Thing valueB",
"SubThing foo",
"SubThing bar",
"Thing valueC",
"Thing valueA",
"SubThing baz",
"SubThing flerp"]
from itertools import accumulate
parents = accumulate((t.startswith("Thing")*i for i,t in enumerate(things)),max)
keys = ((things[p],p,p<i,things[i]) for i,p in enumerate(parents))
sortedThings = [k[-1] for k in sorted(keys)]
for thing in sortedThings: print(thing)
Thing valueA
SubThing baz
SubThing flerp
Thing valueB
SubThing bar
SubThing foo
Thing valueC
Это все итераторы и генераторы. Нет промежуточной структуры данных (кроме внутренней во время сортировки). Все это можно было бы написать в одной (чудовищной) строке, но я старался, чтобы это было понятно.
Как вы и подозревали, это действительно преобразование Шварца, поэтому вы можете играть с кортежем, используемым в keys
(шаг украшения), чтобы получить разные схемы сортировки.
Например, если вы хотите сортировать только между группами «Вещи», но не элементами «Подчинения» в каждой группе, замените (things[p],p,p<i,things[i])
на (things[p],p,i,things[i])
в генераторе keys
.
Если вы хотите только отсортировать элементы «SubThing» в каждой группе, не перемещая группы, измените его на (p,p<i,things[i])
[EDIT ] Я только что заметил, что вы используете Python 2.7, который, как мне кажется, не имеет функции накопления в itertools. В таком случае вы можете написать свой собственный:
def accumulate(iterable,func):
for i,value in enumerate(iterable):
result = func(result,value) if i else value
yield result
Я никогда не использовал Python 2.7, поэтому могут быть некоторые другие отличия, о которых я не знаю