Ошибка сортировки списка объектов в Python с использованием сравнения и lt

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

Может ли кто-нибудь следить за моим кодом и сказать мне, как заставить его работать правильно?

Я создал класс Vertex (Vertice) с его инициализатором, методами __lt__, __gt__ и __cmp__. Кроме того, основная программа создает список Vertex и пытается упорядочить их (безуспешно).


class Vertice:
    def __init__(self, coordenada_x, coordenada_y):
        self.coordenada_x = coordenada_x
        self.coordenada_y = coordenada_y

    def __str__(self):
        return "Vértice ({},{})".format(self.coordenada_x, self.coordenada_y)

    def __add__(self, otro_vertice):
        vertice_resultado = Vertice(self.coordenada_x + otro_vertice.coordenada_x, self.coordenada_y + otro_vertice.coordenada_y)
        return vertice_resultado


    def __lt__(self, otro_vertice):
        if self.coordenada_x > otro_vertice.coordenada_x:
            return -1
        elif self.coordenada_x < otro_vertice.coordenada_x:
            return +1
        else:
            if self.coordenada_y > otro_vertice.coordenada_y:
                return -1
            elif self.coordenada_y < otro_vertice.coordenada_y:
                return +1
            else:
                return 0

    def __gt__(self, otro_vertice):
        if self.coordenada_x > otro_vertice.coordenada_x:
            return +1
        elif self.coordenada_x < otro_vertice.coordenada_x:
            return -1
        else:
            if self.coordenada_y > otro_vertice.coordenada_y:
                return +1
            elif self.coordenada_y < otro_vertice.coordenada_y:
                return -1
            else:
                return 0

    def __cmp__(self, otro_vertice):
        if self.coordenada_x > otro_vertice.coordenada_x:
            return +1
        elif self.coordenada_x < otro_vertice.coordenada_x:
            return -1
        else:
            if self.coordenada_y > otro_vertice.coordenada_y:
                return +1
            elif self.coordenada_y < otro_vertice.coordenada_y:
                return -1
            else:
                return 0

from Vertice import Vertice
import random

def main():
    lista = []
    for i in range(0,10):
        a = random.randint(1,99)
        b = random.randint(1,99)
        lista.append(Vertice(a,b))

    for elemento in lista:
        print(elemento)

    print()

    lista.sort()

    for elemento in lista:
        print(elemento)

    print()

main()

Я ожидаю вывод списка вершин, сначала упорядоченного по координате «x», а затем по координате «y». В этот момент список хаотично переупорядочивается.

__cmp__ больше не используется в python3.
Giacomo Alzetta 03.06.2019 09:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, как указано в документации Шансы и концы по сортировке:

The sort routines are guaranteed to use __lt__() when making comparisons between two objects. So, it is easy to add a standard sort order to a class by defining an __lt__() method

Это также упоминается в документации sort():

This method sorts the list in place, using only < comparisons between items.

Так что вам нужно всего лишь реализовать метод __lt__.
Вам не нужны __gt__ и __cmp__ больше не действует для Python3.

Затем метод __lt__ должен возвращать либо True, либо False.

# is self < other_vertice?
def __lt__(self, other_vertice):        
    if self.x > other_vertice.x:
        return False
    elif self.x < other_vertice.x:
        return True
    else:
        if self.y > other_vertice.y:
            return False
        elif self.y < other_vertice.y:
            return True
        else:
            return False

После этого ваш код в main должен работать:

def main():
    lista = []
    for i in range(0, 10):
        a = random.randint(1, 2)
        b = random.randint(1, 99)
        lista.append(Vertice(a, b))
    print("UNSORTED")
    for elemento in lista:
        print(elemento)

    print("SORTED")
    lista.sort()
    for elemento in lista:
        print(elemento)

main()

Результат:

UNSORTED
Vértice (48,44)
Vértice (5,92)
Vértice (46,10)
Vértice (55,51)
Vértice (63,54)
Vértice (53,85)
Vértice (95,18)
Vértice (69,84)
Vértice (8,20)
Vértice (97,64)
SORTED
Vértice (5,92)
Vértice (8,20)
Vértice (46,10)
Vértice (48,44)
Vértice (53,85)
Vértice (55,51)
Vértice (63,54)
Vértice (69,84)
Vértice (95,18)
Vértice (97,64)

Результат (когда некоторые вершины имеют одинаковые x):

UNSORTED
Vértice (1,88)
Vértice (1,65)
Vértice (2,87)
Vértice (2,4)
Vértice (2,69)
Vértice (2,81)
Vértice (2,5)
Vértice (1,36)
Vértice (1,97)
Vértice (1,73)
SORTED
Vértice (1,36)
Vértice (1,65)
Vértice (1,73)
Vértice (1,88)
Vértice (1,97)
Vértice (2,4)
Vértice (2,5)
Vértice (2,69)
Vértice (2,81)
Vértice (2,87)

Привет Джино, это работает отлично. Большое спасибо за четкое объяснение. Хорошего дня.

user1746636 03.06.2019 13:05

Другие вопросы по теме