Подтвердить что ты не робот

Создайте список кортежей со смежными элементами списка, если условие истинно

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

Список ввода:

myList = [1, 8, 9, 2, 4, 9, 6, 7, 9, 8]

Желаемый результат:

sets = [(8, 9), (4, 9), (7, 9)]

Код:

sets = [list(zip(myList[i:i], myList[-1:])) for i in myList if i==9]

Текущий результат:

[[], [], []]
4b9b3361

Ответ 1

Более чистый питоновский подход:

>>> [(x,y) for x,y in zip(myList, myList[1:]) if y == 9]
[(8, 9), (4, 9), (7, 9)]

Что делает вышеприведенный код:

  • zip(some_list, some_list[1:]) создаст список пар смежных элементов.
  • Теперь с этим кортежем, фильтруйте при условии, что второй элемент равен 9. Вы закончили:)

Ответ 2

Часть вашей проблемы заключается в том, что myList[i:i] всегда будет возвращать пустой список. Конец среза является исключительным, поэтому, когда вы выполняете a_list[0:0], вы пытаетесь взять элементы a_list, которые существуют между индексом 0 и индексом 0.

Вы на правильном пути, но вы хотите закрепить этот список.

[(x, y) for x, y in zip(myList, myList[1:]) if y==9]

Ответ 3

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

sets = [(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9]

Получить индекс в диапазоне длины списка, а если значение в позиции i равно 9, возьмите соседние элементы.

Результат:

sets
[(8, 9), (4, 9), (7, 9)]

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

sets = [(myList[i-1], j) for i, j in enumerate(myList) if j == 9]

Обратите внимание, что в случае края, где myList[0] = 9 поведение понимания без zip, а поведение понимания с помощью zip отличается.

В частности, если myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8], то:

[(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9]
# results in: [(8, 9), (8, 9), (4, 9), (7, 9)]

а

[(x, y) for x, y in zip(myList, myList[1:]) if y==9]
# results in: [(8, 9), (4, 9), (7, 9)]

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

Ответ 4

Вы также можете сделать это без нарезки, создав итераторы:

l = myList = [1,8,9,2,4,9,6,7,9,8]

it1, it2 = iter(l), iter(l)
# consume first element from it2 -> leaving 8,9,2,4,9,6,7,9,8
next(it2, "")
# then pair up, (1,8), (8,9) ...
print([(i, j) for i,j in zip(it1, it2) if j == 9])

Или используйте парный рецепт, чтобы создать свои пары

from itertools import tee, izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Если вы используете python3, просто импортируйте tee и используйте обычный zip.

Ответ 5

Неудивительно, что никто не добавил функциональный подход.

Другой альтернативный ответ - filter. Эта встроенная функция возвращает итератор (список в Python2), состоящий из всех элементов, присутствующих в списке, которые возвращают True для определенной функции

>>> myList = [1,8,9,2,4,9,6,7,9,8]
>>> list(filter(lambda x:x[1]==9,zip(myList, myList[1:])))
[(8, 9), (4, 9), (7, 9)]

Следует отметить, что вызов list требуется только в python3 +. Разница между функциональным подходом и пониманием списков обсуждается в в этом сообщении.

Ответ 6

Мое решение похоже на одно из продвинутых Jim с проверкой нулевого индекса

myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8]

[(myList[i-1], x) for i, x in enumerate(myList) if x==9 and i!=0]

# [(8, 9), (4, 9), (7, 9)]