以递归方式排序python列表

时间:2017-12-08 08:02:12

标签: python python-2.7 sorting

作为输入,我将获得最多可达n级的列表列表,并且每次都会有所不同。假设,我有一个列表

[[2, 1, 3], 4, [2, 3], 7, 1, [9, [4, 2], 5]]

这里我想对此列表进行排序,预期输出为

[1, 4, [2, 3], [1, 2, 3], 7, [5, [2, 4], 9]]

这里,首先基于元素进行排序,然后基于列表内元素的总和。

input_freq = [[2,1,3],4,[2,3],7,1,[9,[4,2],5]]

res = []

def sortFreq(input_freq):
    elements = []
    list_of_elements = []

    for each in input_freq:
        if isinstance(each, list):
            print "list"
            list_of_elements.append(each)
            each.sort()
        else:
            elements.append(each)
            elements.sort()

    print elements
    print list_of_elements

sortFreq(input_freq)

预期产出:

[1, 4, [2, 3], [1, 2, 3], 7, [5, [4, 2], 9]]

但我的代码返回错误的结果:

[[1, 2, 3], [2, 3], [5, 9, [4, 2]]]

2 个答案:

答案 0 :(得分:3)

您必须先按照嵌套级别进行操作,然后在递归调用返回时对父级别进行排序。我假设您要返回一个新列表(而不是排序):

def nested_sort(l):
    def sort_key(e):
        if isinstance(e, list):
            return sum(sort_key(inner) for inner in e)
        return e
    return sorted(
        [nested_sort(e) if isinstance(e, list) else e for e in l],
        key=sort_key)

排序键必须以递归方式对嵌套列表求和,因此如果您有许多嵌套级别,这可能会很昂贵。因此,根据要汇总的列表的标识添加缓存可能是值得的:

def nested_sort(l, _sum_cache=None):
    if _sum_cache is None:
        _sum_cache = {}
    def sort_key(e):
        if isinstance(e, list):
            e_id = id(e)
            if e_id not in _sum_cache:
                _sum_cache[e_id] = sum(sort_key(inner) for inner in e)
            return _sum_cache[e_id]
        return e
    return sorted(
        [nested_sort(e, _sum_cache) if isinstance(e, list) else e for e in l],
        key=sort_key)

演示:

>>> nested_sort([[2, 1, 3], 4, [2, 3], 7, 1, [9, [4, 2], 5]])
[1, 4, [2, 3], [1, 2, 3], 7, [5, [2, 4], 9]]

答案 1 :(得分:0)

这是一个解决方案,它的好处是只需每次执行一次总和。它也很短:

import operator

def sort_lol(lol):
    srtd, sums = zip(*sorted((sort_lol(el) if isinstance(el, list) else (el, el) 
                              for el in lol), key=operator.itemgetter(1)))
    return list(srtd), sum(sums)

lst = [[2,1,3],4,[2,3],7,1,[9,[4,2],5]]
print(sort_lol(lst))

# ([1, 4, [2, 3], [1, 2, 3], 7, [5, [2, 4], 9]], 43)
# note that the function returns the sorted list and the total (43 here)