Задать вопрос
sousagemonster
@sousagemonster

Почему проблема в сортировке?

У меня код для вывода топ игроков моего бота выглядит следующим образом:
@dp.message_handler(commands=['top'])
async def cmd_top(message: types.Message):
    tops = cur.execute("SELECT balance FROM users").fetchall()
    tops.sort()
    top1 = tops[-1][0]
    top2 = tops[-2][0]
    top3 = tops[-3][0]
    top4 = tops[-4][0]
    top5 = tops[-5][0]
    allt = [top1, top2, top3, top4, top5]
    alltops = ""
    num = 0
    for x in allt:
        fname = cur.execute("SELECT fname FROM users WHERE balance=?", (x,)).fetchall()
        num += 1
        alltops += f"{num} • {fname} - <b><i>{x}</i></b> монеток.\n"
    await message.reply(f"Топ 5 богачей бота.\n\n{alltops}")


После ввода команды, в консоли выскакивает ошибка:
tops.sort()
TypeError: '<' not supported between instances of 'NoneType' and 'int'


Помогите пожалуйста решить проблему

Пишу на библиотеке Aiogram
  • Вопрос задан
  • 111 просмотров
Подписаться 1 Простой 1 комментарий
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Код феерический. Два запроса вместо одного, выбор всех строк ради сортировки на клиенте, NULL там, где его быть не должно, и так далее.

Всё это прекрасно делается на уровне запроса к базе!
SELECT fname, balance FROM users WHERE balance IS NOT NULL ORDER BY balance DESC LIMIT 5

Выберет имя и баланс пользователей, у которых баланс не NULL (sql-евский NULL превращается в питоновский None, с которым ты и столкнулся при сортировке). Это, к слову, твоя вина, нужно было указать NOT NULL и значение по умолчанию для поля balance при создании таблицы.
Результат сортируется по полю balance по убыванию, и выбираются не более первых 5 строк (может быть менее).
Каждая строка результата будет кортежем, где нулевой элемент - имя игрока, а первый - баланс.

top5 = cur.execute('SELECT fname, balance FROM users WHERE balance IS NOT NULL ORDER BY balance DESC LIMIT 5').fetchall()
table = []
for num, (fname, x) in enumerate(top5, 1):
    table.append(f'{num} • {fname} - <b><i>{x}</i></b> монеток.\n' )
await message.reply('Топ 5 богачей бота.\n\n'+''.join(table))


Подучи SQL, сильно упростишь себе жизнь при составлении запросов.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
phaggi
@phaggi Куратор тега Python
лужу, паяю, ЭВМы починяю
Видимо, БД возвращает среди значений пустые значения, что и вызывает ошибку. Вот её модель:
tops = [(1,), (2,), (3,), (4,), (None,), (7,)]
tops.sort()

Проверьте, что возвращает select. Возможно, перед сортировкой надо убедиться, что None отсутствуют, или пройтись циклом и преобразовать все None в нулевое значение int.

spoiler
Также конструкция со множеством присваиваний выглядит ужасно. Вот вариант:
tops = [(1,), (2,), (3,), (4,), (None,), (7,)]

tops = [(0, ) if item[0] == None else item for item in tops]
allt = [item[0] for item in sorted(tops, reverse=True)][:5]
print(allt)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы