Этот вопрос уже имеет ответ здесь:
Я чувствую, что трачу большое написание кода времени в 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)]
который имеет побочный эффект выбрасывания последнего числа в случае, который длина даже не.
Существует ли более идиоматический подход, который я пропускаю, или действительно ли это является лучшим, я собираюсь добраться?
Это сделает это немного более аккуратно:
>>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]
(но, возможно, менее читабельно, если вы не знакомы со свойством диапазонов "stride").
Как и ваш код, он отбрасывает последнее значение, если у вас нечетное количество значений.
Правильнее всего, вероятно, не вычислять списки, а написать функцию итератор-> итератор. Это более общий подход - он работает с каждой итерацией, и если вы хотите «заморозить» его в списке, вы можете использовать функцию «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 еще нет функции для этого - возможно, в будущей версии. А пока вы можете использовать версию, указанную выше :)
Как насчет использования пошаговой функции range ()
:
[(l[n],l[n+1]) for n in range(0,len(l),2)]
Если вы не хотите терять элементы, если их количество в списке не указано даже попробуйте это:
>>> 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)]
Обычно для этого я копирую рецепт 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)
Часто цитируемый вариант:
zip(*[iter(l)] * 2)
Я предпочитаю эту более читабельную версию итер
решения:
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
попробуйте это
def pairs(l, n):
return zip(*[l[i::n] for i in range(n)])
Итак,
пары ([1, 2, 3, 4], 2)
дает
[(1, 2), (3, 4)]