Питон "Каждый другой элемент" Идиома
Мне кажется, что я трачу много времени на написание кода на Python, но недостаточно времени на создание Pythonic-кода. Недавно я столкнулся с забавной проблемой, которая, как я думал, может иметь легкое идиоматическое решение. Перефразируя оригинал, мне нужно было собрать каждую последовательную пару в списке. Например, учитывая список [1,2,3,4,5,6]
, я хотел вычислить [(1,2),(3,4),(5,6)]
.
В то время я придумал быстрое решение, похожее на переведенную Java. Повторяя вопрос, лучшее, что я мог сделать, это
l = [1,2,3,4,5,6]
[(l[2*x],l[2*x+1]) for x in range(len(l)/2)]
который имеет побочный эффект отбрасывания последнего числа в случае, когда длина не четная.
Есть ли более идиоматический подход, который мне не хватает, или это лучшее, что я собираюсь получить?
Ответы
Ответ 1
Это будет делать это более аккуратно:
>>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]
(но это, возможно, менее читаемо, если вы не знакомы с функцией "шага" диапазонов).
Как и ваш код, он отбрасывает последнее значение, в котором у вас есть нечетное число значений.
Ответ 2
Часто цитируется:
zip(*[iter(l)] * 2)
Ответ 3
Я обычно копирую рецепт grouper
из itertools в свой код для этого.
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
Ответ 4
Как использовать функцию шага range()
:
[(l[n],l[n+1]) for n in range(0,len(l),2)]
Ответ 5
попробуйте это
def pairs(l, n):
return zip(*[l[i::n] for i in range(n)])
Итак,
pairs([1, 2, 3, 4], 2)
дает
[(1, 2), (3, 4)]
Ответ 6
Правильная вещь - это, вероятно, не вычисление списков, а запись функции iterator- > iterator. Это более общий - он работает на каждом истребимом, и если вы хотите "заморозить" его в списке, вы можете использовать функцию "list()".
def groupElements(iterable, n):
# For your case, you can hardcode n=2, but I wanted the general case here.
# Also, you do not specify what to do if the
# length of the list is not divisible by 2
# I chose here to drop such elements
source = iter(iterable)
while True:
l = []
for i in range(n):
l.append(source.next())
yield tuple(l)
Я удивлен, что модуль itertools еще не имеет функции для этого - возможно, будущей версии. До тех пор не стесняйтесь использовать версию выше:)
Ответ 7
toolz - это хорошо построенная библиотека с множеством функциональных программных тонкостей, забытых в itertools. partition
разрешает это (с возможностью вставить последнюю запись для списков нечетной длины)
>>> list(toolz.partition(2, [1,2,3,4,5,6]))
[(1, 2), (3, 4), (5, 6)]
Ответ 8
Если вы не хотите терять элементы, если их число в списке даже не пытается это сделать:
>>> l = [1, 2, 3, 4, 5]
>>> [(l[i], l[i+1] if i+1 < len(l) else None) for i in range(0, len(l), 2)]
[(1, 2), (3, 4), (5, None)]