#python
#python
Вопрос:
Я хочу знать, кто самый высокий спортсмен (объект) в списке объектов. Если я хочу его распечатать, я попытался написать это:
print ("The greater height is",max(x.height for x in athletes_list),"meters.")
Он показывает рост более высокого спортсмена, но я не знаю, как получить его имя таким образом, поместив все команды в тело print. Есть ли какой-либо способ сделать это?
Я знаю, что это возможно, создав для этого:
for i in athletes_list:
if i.height==max(x.height for x in athletes_list):
print ("The taller athlete is",i.name,"with",i.height,"meters.")
Возможно ли получить обе информации только в теле print?
Извините за плохой английский.
Комментарии:
1. Что, если есть более одного спортсмена с самым высоким ростом?
2. Вы ищете argmax. В Python это делается следующим образом
max(iterable, key=lambda x: ...)
3. Хорошая точка зрения, @thefourtheye. Я попытаюсь найти это решение самостоятельно, используя ответы, которые я нашел здесь, и немного логики. Но если кто-то хочет указать способ, это было бы неплохо 😉
Ответ №1:
Перечитайте свой вопрос. Ответ по-прежнему положительный. Используйте format
метод строк:
print("The taller athlete is {0.name} with {0.height} meters.".format(max(athletes_list, key=lambda a: a.height)))
Комментарии:
1. Да, он также может отсортировать список:
athletes_list.sort(key=lambda a: a.height, reverse=True)
и выбрать первого спортсмена.2. @LaurentLAPORTE: Конечно, если ему нужен только первый, стоимость a
sort
равнаO(n log n)
, по сравнению сO(n)
formax
, так что это ценно, только если ему действительно нужно, чтобы они все были отсортированы.3. @LaurentLAPORTE плюс, который изменяет список, что может иметь последствия позже
4. Да, согласен с вами, я только даю другое решение в комментарии (это не ответ).
5. Потрясающе! Большое спасибо!
Ответ №2:
Используйте max
для обоих значений (сначала с высотой):
from future_builtins import map # Only on Py2, to get generator based map
from operator import attrgetter
# Ties on height will go to first name alphabetically
maxheight, name = max(map(attrgetter('height', 'name'), athletes))
print("The taller athlete is", name, "with", maxheight, "meters.")
Или таким образом, связи разрешаются по порядку появления, а не по имени:
maxheight, name = attrgetter('height', 'name')(max(athletes, key=attrgetter('height')))
Комментарии:
1. Большинство разработчиков действительно не понимают
attrgetter
, я предпочитаю использоватьlambda
withmax()
, как в других ответах.2.@LaurentLAPORTE: Большинство разработчиков также не используют
map
правильно (если вы используете его сlambda
, вы пессимизируете и должны просто использовать listcomp или genexpr вместо этого). Я предпочитаюattrgetter
иitemgetter
, потому что они самодокументируются и сигнализируют «здесь нет трюков». Они также быстрее и хорошо масштабируются для одновременного получения многих значений. Я используюlambda
s только тогда, когда есть хитрости (например, ключ сортировкиlambda x: x[0], -x[2], x[1]
, обратите внимание на-
onx[2]
, который делаетitemgetter(0, 2, 1)
непригодным), поэтому, когда я вижуlambda
s в своем коде, я знаю, что нужно проверить более тщательно. Хотя не стоит опускать голос.3. Хороший вариант. Работает как шарм, но я думаю, что этот способ немного сложнее, чем lamba с max() на данный момент.
4. @EduardoM: Верно. Вторая версия
attrgetter
бессмысленна; Я бы действительно просто сохранил спортсмена и использовалtallest.height
иtallest.name
, когда просматриваю каждый из них только один раз. Я просто развлекаюсь здесь. 🙂