Увеличить переменную в понимании с оператором if? - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь изучить Python, но я застрял. Я пытаюсь увеличить мою count переменную, когда условие True и return, которые считаются после цикла. Вот мой код:

list = [1,2,4,5,7,8,10]
d = 3
count = 0
return [count for x in range(len(list))
        if list[x] + d in list and list[x] + 2 * d in list]

Он возвращается "0" каждый раз, когда мое состояние True. Когда я пытаюсь добавить count += 1 в понимание, это дает мне SyntaxError.

Ответы [ 5 ]

0 голосов
/ 11 мая 2018

Не?

for x in lst:
    if x+d in lst and x+2*d in lst:
        count += 1

Или используйте len:

count = len([_ for x in lst if x+d in lst and x+2*d in lst])

Или используйте сумму:

count = sum(1 for x in lst if x+d in lst and x+2*d in lst)

Или используйте наборы (приготовьтесь удивляться):

count = len(({x + d for x in lst} | {x + 2 * d for x in lst}) & set(lst))

Вот номера исполнения в списке из 1000 последовательных чисел:

loop:    20.3 ms ± 8 ms
len:     25.4 ms ± 8.22 ms
sum:     18.3 ms ± 5.06 ms
sets:    272 µs ± 19 µs  (~100x faster)

Это не гарантия исполнения.Наборы также являются, вероятно, наименее эффективным решением в этом случае.Но это работает (на первый взгляд, довольно хорошо).

Кроме того, не называйте переменную list, это встроенная функция в Python, и ее перезапись приведет к всевозможным беспорядкам.

0 голосов
/ 11 мая 2018

Понимания не работают таким образом. Концептуально они позволяют устанавливать и фильтровать отдельные элементы списка, а не накапливать их в одной переменной.

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

В качестве дальнейшего улучшения я бы порекомендовал использовать генераторное выражение вместо понимания списка. Выглядит почти так же, но поддерживает ленивую оценку. Это означает, что вы получаете все преимущества однострочника без необходимости хранить список значений флагов в памяти.

Вот как будет выглядеть первый вариант:

L = [1,2,4,5,7,8,10]
count = sum((x + d in L and x + 2 * d in L) for x in L)

Второй вариант будет выглядеть так:

L = [1,2,4,5,7,8,10]
count = sum(1 for x in L if (x + d in L and x + 2 * d in L))    

Обратите внимание, что я переименовал вашу переменную list в L, чтобы она не затеняла встроенную функцию.

0 голосов
/ 11 мая 2018
list = [1,2,4,5,7,8,10]

d = 3

# python 3 required for _
result = len([_ for x in range(len(list))
                if list[x]+d in list and list[x]+2*d in list])
# python 2
result = len([1 for x in range(len(list))
                if list[x]+d in list and list[x]+2*d in list])
0 голосов
/ 11 мая 2018

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

len([count for x in range(len(list)) 
           if list[x]+d in list and list[x]+2*d in list])

Помните, что это список понимания; Вы не можете добавлять произвольные действия., например, присваивание.

0 голосов
/ 11 мая 2018

Вы очень близки.Постижения списка не могут хранить и повторно использовать переменные так, как вы хотите;они могут содержать только выражения.Одним из решений является использование sum с выражением генератора.

Преимущество этого решения состоит в том, что вы избегаете затрат на построение списка, который не является необходимым для подсчета количества элементов, удовлетворяющих условию.

A = [1,2,4,5,7,8,10]
A_set = set(A)

d = 3
count = 0

res = sum(1 for x in range(len(A)) if \
          (A[x]+d in A_set) and (A[x]+2*d in A_set))

# 3

Обратите внимание, что вы никогда не должны называть переменные после классов.Кроме того, вы можете использовать set для поиска O (1).

Также обратите внимание, что мы создаем A_set вне понимания списка, в противном случае он будет вычисляться для каждой итерации range(len(A)).

...