在 Python 中使用 lambda 表达式(在 1 行中)自定义二维列表排序

我有一个像这样的python 2D列表-

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

我喜欢让它在两个方向上排序,行和列。所以,我想要的输出是这样的 -

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

我所做的是——

list.sort(key = lambda x: (x[1], x[0]))

而我得到的是——

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

谁能帮忙用 in-place 表达式对它进行排序 lambda 吗?

stack overflow Custom 2D list sort with lambda expression (in 1 line) in Python
原文答案
author avatar

接受的答案

key 参数(和 lambda )并不意味着修改 list 的内容。相反,它用于根据应用 key 函数时每个元素的评估方式进行排序。但是,您可以使用 key 的副作用通过在 .sort() 的函数参数上调用 key 来实现您想要的。由于 .sort() 结果只是 None ,您还需要提供用于实际排序的语句本身:

l = [[3,4],[1,2],[2,1],[6,5]]

l.sort(key=lambda x: (x.sort(), x))

print(l)
# [[1, 2], [1, 2], [3, 4], [5, 6]]

但是,这不被认为是好的编程习惯。

一种更清洁、更高效但显然不是 1 线的方法是:

l = [[3,4],[1,2],[2,1],[6,5]]
for x in l:
    x.sort()
l.sort()

print(l)
# [[1, 2], [1, 2], [3, 4], [5, 6]]

基于 key 的方法的效率也显着降低,因为它试图在每次 key 调用时对内部列表进行排序,我们应该预期会发生 n log n 次,而严格要求 n 次,因此一些内部列表不可避免地被排序得比必要的多。相反,循环遍历外部列表对每个内部列表显式排序一次。

只是为了给出一些时间安排的想法:

import random
import copy
import collections

def double_sort_loop(seq):
    for x in seq:
        x.sort()
    seq.sort()

def double_sort_deque(seq):
    collections.deque(map(lambda x: x.sort(), seq), maxlen=0)
    seq.sort()

def double_sort_key(seq):
    seq.sort(key=lambda x: (x.sort(), x))

def gen_input(n, m, v_min=None, v_max=None):
    if v_min is None:
        v_min = 0
    if v_max is None:
        v_max = v_min + (2 * m * n)
    return [[random.randint(v_min, v_max) for _ in range(m)] for _ in range(n)]

random.seed(0)

base = gen_input(100000, 10)

%timeit seq = copy.deepcopy(base); double_sort_loop(seq)
# 1 loop, best of 3: 1.03 s per loop
%timeit seq = copy.deepcopy(base); double_sort_deque(seq)
# 1 loop, best of 3: 1.02 s per loop
%timeit seq = copy.deepcopy(base); double_sort_key(seq)
# 1 loop, best of 3: 1.19 s per loop

答案:

作者头像

如果你 really 想就地在线完成所有这些,你可以用像这样可怕的东西来实现它:

vals = [[3, 4], [1, 2], [2, 1], [6, 5]]

vals.sort(key=lambda x: (lambda x, dummy: (x[1], x[0]))(x, x.sort()))

print(vals)

输出: [[1, 2], [1, 2], [3, 4], [5, 6]]

虽然这确实符合您的要求,但效率低下且无法阅读。我强烈建议按照其他答案中的说明正确执行此操作。

作者头像

您不能就地排序,因为您需要首先创建修改后的内部元素列表。你能做的最好的就是

[sorted(x) for x in my_list].sort(key=lambda k: (k[0], k[1]))