Сортировать список кортежей, переупорядочивая кортежи

Учитывая список кортежей для сортировки, python будет сортировать их по первому элементу в кортеже, тогда второй элемент и т.д.

>>> A
[(3, 2, 1), (0, 3, 0), (2, 1, 0), (2, 2, 3), (0, 3, 2), (2, 1, 1), (3, 3, 2), (3, 2, 0)]
>>> sorted(A)
[(0, 3, 0), (0, 3, 2), (2, 1, 0), (2, 1, 1), (2, 2, 3), (3, 2, 0), (3, 2, 1), (3, 3, 2)]

Это отлично работает. Теперь я хочу отсортировать их по третьему элементу, затем первому элементу, а затем второму элементу, который я могу сделать, либо предоставив ключевую функцию, либо функцию cmp.

>>> A
[(3, 2, 1), (0, 3, 0), (2, 1, 0), (2, 2, 3), (0, 3, 2), (2, 1, 1), (3, 3, 2), (3, 2, 0)]
>>> sorted(A, key = lambda x: (x[2], x[0], x[1]))
[(0, 3, 0), (2, 1, 0), (3, 2, 0), (2, 1, 1), (3, 2, 1), (0, 3, 2), (3, 3, 2), (2, 2, 3)]

за исключением того, что я выполняю серьезную оценку производительности

s ="""\
from numpy.random import randint as rr
A=[tuple(rr(0,10,3)) for i in range(100)]
def tuplecmp(t1, t2):
 return t1[0] - t2[0]
"""
c1 = """\
sorted(A)
"""
c2 = """\
sorted(A, key=lambda x: (x[2], x[0], x[1]))
"""
c3 = """\
sorted(A, cmp = tuplecmp)
"""
import timeit
print timeit.timeit(c1,number=10000, setup= s)
print timeit.timeit(c2,number=10000, setup= s)
print timeit.timeit(c3,number=10000, setup= s)

дает

0.60133600235,
0.980231046677,
2.68837809563

Кроме того, порядок, в котором я сравниваю отдельные элементы кортежа, не должен оставаться таким же. Мне может потребоваться сравнить элемент "второй, первый, третий" и т.д. Существует ли более эффективный способ предоставления произвольных функций компаратора без существенного снижения производительности;

2 ответа

Использование operator.itemgetter для вашей функции key может быть быстрее; вам придется попробовать.

import operator
sorted(A, key=operator.itemgetter(2, 0, 1))


Я не знаю лучшего способа сделать то, что вы пытаетесь сделать. Я считаю, что вам всегда придется поставлять свой собственный компаратор, а затем оплачивать расходы на вызов снова и снова.

licensed under cc by-sa 3.0 with attribution.