在没有排序功能的情况下按特定元素对嵌套列表进行排序。

时间:2017-05-11 05:43:26

标签: python list sorting nested

如果我有这样的嵌套列表:

L = [['James', '1', '2'], ['Alan', '1', '1'], ['Henry', '1', '5']]

如何根据每个子列表中的最后一个数字从最高到最低排序,而不使用排序或排序函数?

输出:

final = [['Henry', '1', '5'], ['James', '1', '2'], ['Alan', '1', '1']]

我知道如何做的唯一方法是使用排序功能,但我想知道如何在没有它的情况下做到这一点。

3 个答案:

答案 0 :(得分:0)

L = [['James', '1', '2'], ['Alan', '1', '1'], ['Henry', '1', '5']]

keys = [(int(v[-1]),k) for k,v in enumerate(L)]
final = []

for i in range(len(keys)):
    #find the next biggest element according to last element of the list.
    final.append(L[max(keys)[-1]])
    keys[max(keys)[-1]] = ''

final
Out[83]: [['Henry', '1', '5'], ['James', '1', '2'], ['Alan', '1', '1']]

答案 1 :(得分:0)

可以实施许多sorting algorithms。很久以前,蒂姆·彼得斯在Python sorted内置thoughtfully implemented

但是,这是另一个使用heapq的排序选项:

import heapq
import operator as op

heapq.nlargest(len(L), L, key=op.itemgetter(-1))
# [['Henry', '1', '5'], ['James', '1', '2'], ['Alan', '1', '1']]

相比之下,请注意与sorted的相似性,它有几个直观的选项:

import operator as op

expected = [['Henry', '1', '5'], ['James', '1', '2'], ['Alan', '1', '1']]

r1 = sorted(L, key=op.itemgetter(-1))[::-1]
r2 = sorted(L, key=op.itemgetter(-1), reverse=True)
r3 = list(reversed(sorted(L, key=op.itemgetter(-1))))

assert r1 == r2 == r3 == expected

sorted通常很快,但有heapq更快的例外情况。有关详细信息,另请参阅this post

答案 2 :(得分:0)

您可以编写自己的quicksort功能。你几乎可以切换一些标志来反转输出:

def quicksort(arr):
    if len(arr) <= 1:
        return arr

    pivot = arr[len(arr)/2]

    left = [x for x in arr if x > pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x < pivot]

    return quicksort(left) + middle + quicksort(right)

下一步是确保你提取正确的数字,并确保你可以将它们映射回父列表,这样你就可以将它们放到正确的位置 - Allen's answer有一个好的的方法:

L = [['James', '1', '2'], ['Alan', '1', '1'], ['Henry', '1', '5']]

keys = [(int(v[-1]),k) for k,v in enumerate(L)] # This line here

该行基本上创建了一个元组列表,用于存储我们要排序的数字,以及该数字在父级列表中的父列表的索引。基本上,对于Lkeys = [(2, 0), (1, 1), (5, 2)]

因此,您可以通过创建可递归使用的子函数来更改quicksort函数以解决所有这些问题:

def quicksort(arr):
    # Put the actual sorting function into a subfunction that can be called recursively
    def subsort(arr2):
        if len(arr2) <= 1:
            return arr2
        pivot = arr2[len(arr2)/2]
        left = [x for x in arr2 if x > pivot]
        middle = [x for x in arr2 if x == pivot]
        right = [x for x in arr2 if x < pivot]
        return subsort(left) + middle + subsort(right)

    # Get the value-key pairs and sort them
    keys = [(int(v[-1]),k) for k,v in enumerate(L)]
    keys = subsort(keys)

    # Do the mapping back to the original array fed into the main function
    final = []
    for i in keys:
        final.append(arr[i[1]])

    return final

随之而来:

>>> L = [['James', '1', '2'], ['Alan', '1', '1'], ['Henry', '1', '5']]
>>> quicksort(L)
[['Henry', '1', '5'], ['James', '1', '2'], ['Alan', '1', '1']]

注意:如果在最后一个位置有两个具有相同编号的项目,那么这些项目将在原始列表中获得原始相对位置(相互之间)还原 。有关元组比较的更多详细信息,请参阅this answer,并注意我们在此处按降序顺序对事物进行排序(否则,它们只是保持原始位置相对于彼此)。所以:

>>> L = [['Simon', '1', '2'], ['Henry', '1', '5'], ['Finn', '1', '2']
>>> quicksort(L)
[['Henry', '1', '5'], ['Finn', '1', '2'], ['Simon', '1', '2']]