Задача "сумма двух" и списковое включение
Пытался решить задачку "Сумма двух" с помощью спискового включения, однако столкнулся с ошибкой:
did you forget parentheses around the comprehension target?
Основной код:
nums = [3,2,4]
target = 6
for x in range(len(nums)):
if target - nums[x] in nums[x+1:len(nums)]:
print([x, nums.index(target - nums[x], x+1, len(nums))])
break
Главное, на входе получить список из size>=2
элементов, также получить значение, которое должно получится при сложении двух чисел target
. В коде указал пример входа.
В попытках создать списковое включение
:
outputList = [x, nums.index(target - nums[x], x+1, len(nums)) for x in range(len(nums)) if target - nums[x] in nums[x+1:len(nums)] == True]
print(outputList)
Я, конечно, понимаю, что я могу нарушать стиль PEP8
, однако ради обучения можно отойти от стиля написания кода.
Ожидаемый вывод индексов в виде списка:
[1,2]
Опирался на реализацию этой строки:
new_list = [x for x in range(1, 10) if x % 2 == 0 if x % 3 == 0]
Однако результат трансляции моего кода отрицательный и чего-то недостаёт, я не могу заметить этого.
UPD:
outputList = [[x, nums.index(target - nums[x], x+1, len(nums))] for x in range(len(nums)) if target - nums[x] in nums[x+1:len(nums)] == True]
print(outputList)
После добавления []
, мы можем указывать несколько переменных, однако вывод становится пустым.
Ответы (3 шт):
Суммаризация комментариев:
Условие
target - nums[x] in nums[x+1:len(nums)] == True
Априори ложное, так как сначала проверяется равенство
nums[x+1:len(nums)] == True
А только затем
target - nums[x] in False # False <=> nums[x+1:len(nums)] == True
Убрав это сравнение, и оставив лишь
outputList = [[x, nums.index(target - nums[x], x+1, len(nums))] for x in range(len(nums)) if target - nums[x] in nums[x+1:len(nums)]]
Получим желаемый результат
Исходный код из вопроса, отформатированный так, чтобы была заметна проблема:
outputList = [
x,
nums.index(target - nums[x], x + 1, len(nums))
for x in range(len(nums))
if target - nums[x] in nums[x + 1:len(nums)] == True
]
Проблема в том, что компилятор выражение [A, B]
разбирает как список из двух элементов. Второй элемент – выражение-генератор, а генераторы всегда должны быть в скобках.
Автор вопроса хотел другого: что бы было одно выражение генератор, создающее список из пар. Для этого пару надо забрать в скобки, круглые для кортежа, квадратные для списка. Какой вариант выбрать, дело вкуса:
outputList = [
(x, nums.index(target - nums[x], x + 1, len(nums)))
for x in range(len(nums))
if target - nums[x] in nums[x + 1:len(nums)] == True
]
outputList = [
[x, nums.index(target - nums[x], x + 1, len(nums))]
for x in range(len(nums))
if target - nums[x] in nums[x + 1:len(nums)] == True
]
Теперь код компилируется, но не работает: результат всегда пустой. Потому что условие target - nums[x] in nums[x + 1:len(nums)] == True
вычисляется неожиданным для программиста способом.
Замечу что == True
– почти всегда ошибка. Оно не нужно в большинстве случаев. Если написать target - nums[x] in nums[x + 1:len(nums)]
всё будет работать как надо.
Вернёмся к A in B == C
. Это Питон, и цепочки сравнений, а in
и ==
– сравнения, в нём компилируются специальным образом, а именно A in B and B == C
. В нашем случае второй операнд and
всегда ложный, ложно и целиком выражение.
Специальная компиляция сделана что бы вы могли следовать математической нотации в неравенствах: A < B < C
будет скомпилировано как A < B and B < C
. Это удобно, но отличается от других языков и вводит в заблуждение когда вы пишите штуки вроде A in B == C
. Ставьте скобки, чтобы компилятор вас понял: (A in B) == C
. Но, повторюсь, == True
тут не нужно совсем.
Такой вариант будет работать, но медленно:
outputList = [
(x, nums.index(target - nums[x], x + 1, len(nums)))
for x in range(len(nums))
if target - nums[x] in nums[x + 1:len(nums)]
]
TODO: предложить быстрое решение на генераторах списков.
Готовый скрипт для тестирования:
import os
print("-" * 50 + "\nСумма двух чисел в списке с заданным результатом:\n" + "-" * 50)
def two_sum(nums, target):
# Создаем пустой словарь для хранения чисел и их индексов
num_to_index = {}
# Проходим по каждому числу в массиве
for i, num in enumerate(nums):
# Вычисляем дополнение, которое вместе с текущим числом даст в сумме target
complement = target - num
# Проверяем, есть ли дополнение в словаре
if complement in num_to_index:
# Если есть, возвращаем индексы текущего числа и дополнения
indices = [num_to_index[complement], i]
# Выводим сумму элементов результирующего списка
print(f"Сумма элементов: {nums[indices[0]] + nums[indices[1]]}")
return indices
# Если дополнения нет, добавляем текущее число и его индекс в словарь
num_to_index[num] = i
# Если решение не найдено, возвращаем пустой список
return []
# Пример использования
nums = [2, 7, 11, 15]
target = 9
print(two_sum(nums, target)) # Вывод: [0, 1]
print("\nНажмите любую клавишу для продолжения...")
os.system("pause > nul" if os.name == "nt" else "read > /dev/null")