Python将矩阵行排序为行级... ...

时间:2017-11-20 06:57:48

标签: python arrays sorting matrix

我正在试图弄清楚如何在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有一种首选方式(我正在看着你,列出理解)。

1 个答案:

答案 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