Python “любой элемент” идиома [дубликат]

Этот вопрос уже имеет ответ здесь:

Я чувствую, что трачу большое написание кода времени в 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)]

который имеет побочный эффект выбрасывания последнего числа в случае, который длина даже не.

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

38
задан Matt Luongo 13 April 2010 в 16:11
поделиться

7 ответов

Это сделает это немного более аккуратно:

>>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]

(но, возможно, менее читабельно, если вы не знакомы со свойством диапазонов "stride").

Как и ваш код, он отбрасывает последнее значение, если у вас нечетное количество значений.

81
ответ дан 27 November 2019 в 02:59
поделиться

Правильнее всего, вероятно, не вычислять списки, а написать функцию итератор-> итератор. Это более общий подход - он работает с каждой итерацией, и если вы хотите «заморозить» его в списке, вы можете использовать функцию «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 еще нет функции для этого - возможно, в будущей версии. А пока вы можете использовать версию, указанную выше :)

4
ответ дан 27 November 2019 в 02:59
поделиться

Как насчет использования пошаговой функции range () :

[(l[n],l[n+1]) for n in range(0,len(l),2)]
8
ответ дан 27 November 2019 в 02:59
поделиться

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

>>> 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)]
3
ответ дан 27 November 2019 в 02:59
поделиться

Обычно для этого я копирую рецепт 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)
9
ответ дан 27 November 2019 в 02:59
поделиться

Часто цитируемый вариант:

zip(*[iter(l)] * 2)

Я предпочитаю эту более читабельную версию итер решения:

it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
49
ответ дан 27 November 2019 в 02:59
поделиться

попробуйте это

def pairs(l, n):
    return zip(*[l[i::n] for i in range(n)])

Итак,

пары ([1, 2, 3, 4], 2) дает

[(1, 2), (3, 4)]
4
ответ дан 27 November 2019 в 02:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: