Как отсортировать список списков, содержащих определенные пользователем объекты - PullRequest
1 голос
/ 27 мая 2020

У меня есть следующий список списков "category" объектов в переменной с именем "category_tree", которая является списком:

[[<Category: State>, <Category: County>, <Category: Chicago>], 
[<Category: Animal>],
[<Category: State>, <Category: County>], 
[<Category: State>, <Category: County>, <Category: NYC>], 
[<Category: Animal>, <Category: Fish>], 
[<Category: State>, <Category: County>, <Category: LA>], 
[<Category: Animal>, <Category: Frog>, <Category: TreeFrog>, <Category: Fred>]]

Мне нужно отсортировать list верхнего уровня по .name свойства базового lists. Я не хочу сортировать базовые списки, а только верхний уровень list.

Предполагая, что элементы .name соответствуют перечисленным здесь, я пытаюсь получить следующее:

[[<Category: Animal>], 
[<Category: Animal>, <Category: Fish>], 
[<Category: Animal>, <Category: Frog>, <Category: TreeFrog>, <Category: Fred>]
[<Category: State>, <Category: County>], 
[<Category: State>, <Category: County>, <Category: Chicago>],
[<Category: State>, <Category: County>, <Category: LA>], 
[<Category: State>, <Category: County>, <Category: NYC>]]

Я могу отсортировать их по первому или последнему столбцу с помощью:

category_tree.sort(key=lambda x: x[0].name)
category_tree.sort(key=lambda x: x[-1].name)

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

Как лучше всего это сделать?

1 Ответ

2 голосов
/ 27 мая 2020

Слегка измененный пример с возможным решением:

class Category:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name

items = [
    [Category('State'), Category('County'), Category('Chicago')],
    [Category('Animal')],
    [Category('State'), Category('County')],
    [Category('Animal'), Category('Frog')],
    [Category('Animal'), Category('Fish'), Category('Dog')],
]

items.sort(key=lambda x: [item.name for item in x])
print(items)

приводит к

[[Animal], [Animal, Fish, Dog], [Animal, Frog], [State, County], [State, County, Chicago]]

Это зависит от способности Python напрямую сравнивать списки, при условии, что элементы в списке можно правильно сравнивать. Для целых чисел, чисел с плавающей запятой и строк это не проблема. Для класса (basi c) это так, поскольку он не определен по умолчанию.

Если у вас есть доступ к классу Category (т. Е. Вы написали его самостоятельно), вы можете переопределить __eq__ и другие методы сравнения magi c, что значительно упрощает работу (см., например, Сравнить экземпляры объектов на равенство по их атрибутам ).

С помощью модуля functools:

from functools import total_ordering

@total_ordering 
class Category:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __lt__(self, other):
        return self.name < other.name

    def __repr__(self):
        return self.name

А потом просто:

items.sort()

(items как раньше).

С тем же результатом: [[Animal], [Animal, Fish, Dog], [Animal, Frog], [State, County], [State, County, Chicago]].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...