Python - сортировка списка по атрибуту объекта в порядке, указанном во втором списке ... можно ли это улучшить? - PullRequest
1 голос
/ 05 февраля 2020

У меня есть список неизменяемых объектов, которые мне нужно отсортировать, используя атрибут в качестве ключа.

Объекты должны быть в заданном порядке, а не просто по возрастанию / убыванию.

Я написал некоторый код, который делает это, но у меня нет большой уверенности, что он будет хорошо работать с большими списками (где «большой» полностью произвольный). Сегодняшний вариант использования - это только небольшие списки (12 элементов или меньше), но я живу достаточно долго, чтобы ожидать, что в конечном итоге на него будет брошен большой.

Есть ли другой подход, библиотека или ярлык, который я может быть в состоянии сделать эту операцию более эффективной?

# setup
class Demo(object):
    def __init__(self, pk):
        self.pk = pk

    def __repr__(self):
        return f'<Demo: {self.pk}>'

# instantiating objects for the sake of demonstration; actual input I'm given is random!
objects = [Demo(x) for x in range(10)]
# output object should be sorted by pk attribute, with values in this order
ordinality = [9, 0, 8, 4, 5, 1, 3, 7, 6, 2]

# operation in question
result = (next(obj for obj in objects if obj.pk == ordinal) for ordinal in ordinality)

print(tuple(result))
>>> (<Demo: 9>, <Demo: 0>, <Demo: 8>, <Demo: 4>, <Demo: 5>, <Demo: 1>, <Demo: 3>, <Demo: 7>, <Demo: 6>, <Demo: 2>)

Ответы [ 3 ]

2 голосов
/ 05 февраля 2020

Если предположить, что «pk» означает «первичный ключ» (уникальный), то вместо использования списка таких объектов (с O (n) членством) вы можете просто использовать dict (с O (1) членство)

objects = [Demo(x) for x in range(10)]  # O(n) space
result = [next(obj for obj in objects if obj.pk == ordinal] for ordinal in ordinality)  # O(n^2) time

objects = {x: Demo(x) for x in range(10)}  # O(n) space
result = [objects[pk] for pk in ordinal]  # O(n) time
1 голос
/ 05 февраля 2020

Сначала создайте справочную таблицу, а затем используйте ее. Превращает ваш O (n 2 ) в O (n).

lookup = {obj.pk: obj for obj in objects}
result = [lookup[ordinal] for ordinal in ordinality)
0 голосов
/ 05 февраля 2020

Вы можете просто использовать ординальность для создания объектов. Поскольку ординальность - это порядок, с которого вы хотите начать.

ordinality = [9, 0, 8, 4, 5, 1, 3, 7, 6, 2]

objects = list(map(Demo, ordinality))
#or
objects = [Demo(pk) for pk in ordinality]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...