Pythonic пропорция расчета двух условий

1

Вот очень простой вопрос о питоническом кодировании.

Учитывая список, если вы хотите рассчитать долю элементов, удовлетворяющих (A и B), из тех, которые удовлетворяют (A), естественным решением будет:

Представьте, что список целых чисел, условие A есть ( > 3), условие B есть ( > 5)

count = 0
correct = 0

for item in items:
  if item > 3:
    count += 1

    if item > 5:
      correct += 1

score = float(correct) / count
print '%.2f' % score

Альтернативное решение:

count = len([1 for i in items if i > 3])
correct = len([1 for i in items if i > 5])

score = float(correct) / count
print '%.2f' % score

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

Спасибо.

  • 3
    (Мне все труднее воспринимать людей, которые говорят «Pythonic», серьезно, особенно когда они используют это три раза подряд ...)
  • 0
    Я не совсем знаю, что такое pythonic , но составление списков для подсчета не должно быть.
Показать ещё 2 комментария
Теги:

3 ответа

6
Лучший ответ

Ваше (альтернативное) решение отлично, за исключением этого небольшого изменения:

count = sum(1 for i in items if i > 3)
correct = sum(1 for i in items if i > 5)

score = float(correct) / count
print '%.2f' % score

Синтаксис, который выглядит как понимание списка без скобок, называется выражением .

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

  • 3
    Кстати, потому что я всегда хотел использовать комплексные числа хотя бы один раз: s = sum(complex(x>3,x>5) for x in items); score = float(s.real)/s.imag ;-)
  • 1
    count = sum(i > 3 for i in items)
1

Это не общее решение, а одно, основанное на вашем вопросе и ответе образца.

Если вы знаете взаимосвязь между двумя условиями, вам не нужно дважды проходить последовательность:

gt3 = [x for x in items if x > 3]
count = len(gt3)
correct = sum(x > 5 for x in gt3)

Эффективное, более общее и все еще питоническое решение может быть:

count, correct = map(sum, zip(*((x > 3, x > 5) for x in items)))

Условия более 3 и 5 можно заменить любыми другими условиями.

  • 0
    Я знаю о zip против izip, но это было бы вне контекста.
0
from itertools import groupby
li={x:len(list(y))for x,y in groupby(l,lambda x:2 if x>5 else 1 if x>3 else 0)}
print(li[2]/(li[1]+li[2]))

python3.1

  • 2
    Вы не хотите создавать список из них, чтобы посчитать что-то.
  • 0
    Я думаю, что одной из причин добавления выражений-генераторов в язык было то, чтобы помочь избежать использования анонимных и подробных лямбда-функций.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню