我正在试图弄清楚如何在Python 3.5中为二维数组编写自定义排序函数。我们的想法是将一个数组转换为一个半行梯形形式,其中任何一行带有前导1移动到其他行的顶部,任何前导0到底部的任何行,其余行在其间排序。您可以在下面看到示例矩阵。
before = [
[5, 3, 1, 2, 3, 1],
[0, 1, -1, 2, -3, 4],
[0, 0, 2, 2, -1, 3],
[1, 2, 5, -2, 4, -3],
[2, 1, 1, -1, 4, 2],
[0, 0, 1, 4, 5, -1]
]
after = [
[1, 2, 5, -2, 4, -3],
[2, 1, 1, -1, 4, 2],
[5, 3, 1, 2, 3, 1],
[0, 1, -1, 2, -3, 4],
[0, 0, 1, 4, 5, -1],
[0, 0, 2, 2, -1, 3]
]
如果我在Java中这样做,我会写一个Comparator对象或compareTo方法。但是在线查看,在Python 3+中,它似乎不再是在排序时使用cmp参数的pythonic方式。
现在我可以使用
for i in range(len(mat)-1, -1, -1):
mat.sort(key=itemgetter(i), reverse=True)
执行此操作,但这不会将第一个非零值为1的行移动到顶部。
我很感激任何人可能必须以最pythonic的方式做到这一点。此外,如果任何人有任何好的资源来学习做其他事情的正确的pythonic方式,我会很感激。我有时会做一些事情,好像我用其他语言编写它们并且没有意识到Python有一种首选方式(我正在看着你,列出理解)。
答案 0 :(得分:1)
您可以尝试以下方式:
mat.sort(key=lambda l: [
(0, 0) if x == 1 else
(2, 0) if x == 0 else
(1, x) for x in l
])
利用元组和列表按字典比较的事实,比较前两个元素,等等。
编辑:
我改变了我的观点,我认为如上所示,与创建比较函数(不是那么清晰)相比,这样做可能是更好的方法,并且更快。
测试代码:
TRIALS = 10000
mat = [
[5, 3, 1, 2, 3, 1],
[0, 1, -1, 2, -3, 4],
[0, 0, 2, 2, -1, 3],
[1, 2, 5, -2, 4, -3],
[2, 1, 1, -1, 4, 2],
[0, 0, 1, 4, 5, -1]
]
@functools.cmp_to_key
def matcmp(a, b):
for ai, bi in zip(a, b):
if (ai == bi): continue
if (0 != ai != 1 and 0 != bi != 1):
return a < b
elif (ai == 1 or bi == 0):
return -1
else:
return 1
else:
return 0
start = time.time()
for i in range(TRIALS):
sorted(mat, key=matcmp)
print(time.time() - start)
start = time.time()
for i in range(TRIALS):
sorted(mat, key=lambda l: [
(0, 0) if x == 1 else
(2, 0) if x == 0 else
(1, x) for x in l
])
print(time.time() - start)
输出:
0.10232377052307129
0.09116077423095703