Iterar sobre todos los dos elementos en una lista

¿Cómo puedo hacer una for bucle o una lista de comprensión, de modo que cada iteración me da dos elementos?

l = [1,2,3,4,5,6]

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

De salida:

1+2=3
3+4=7
5+6=11
InformationsquelleAutor jackhab | 2011-03-22

18 Kommentare

  1. 215

    Usted necesita un pairwise() (o grouped()) implementación.

    Para Python 2:

    from itertools import izip
    
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return izip(a, a)
    
    for x, y in pairwise(l):
       print "%d + %d = %d" % (x, y, x + y)

    O, más en general:

    from itertools import izip
    
    def grouped(iterable, n):
        "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
        return izip(*[iter(iterable)]*n)
    
    for x, y in grouped(l, 2):
       print "%d + %d = %d" % (x, y, x + y)

    En Python 3, se puede reemplazar izip con la incorporada en el zip() función, y la caída de la import.

    Todo el crédito a martineau para su respuesta a mi pregunta, he encontrado que esto es muy eficiente, ya que sólo se repite una vez más de la lista y no crea ningún innecesarios listas en el proceso.

    N. B: Esto no debe ser confundido con el pares receta en Python propia itertools documentación, que los rendimientos s -> (s0, s1), (s1, s2), (s2, s3), ..., como se ha señalado por @lazyr en los comentarios.

    Poco, además de para aquellos que quieran hacer la comprobación de tipos con mypy en Python 3:

    from typing import Iterable, Tuple, TypeVar
    
    T = TypeVar("T")
    
    def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
        """s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
        return zip(*[iter(iterable)] * n)
    • No debe confundirse con los pares de la función sugerido en el itertools sección de recetas, lo que produce s -> (s0,s1), (s1,s2), (s2, s3), ...
    • Hace una cosa diferente. Su versión sólo produce la mitad de la cantidad de pares en comparación con el itertools receta de la función con el mismo nombre. Por supuesto, el suyo es más rápido…
    • Eh? Su función y la función a la que me refería a hacer cosas diferentes, y que era el punto de mi comentario.
    • Oh, yo ver. Humildes disculpas. Debo poner mis gafas!
    • Marnach: sospecho que la diferencia de velocidad es debido más a itertools' pairwise() ser implementadas en términos de tee() que porque vuelve menos datos para cualquier iterable — por supuesto también la realización de un algo diferente de la función por completo, por lo que comparar en todo es cuestionable…
    • CUIDADO! El uso de estas funciones lo pone en riesgo de no iterando sobre los últimos elementos de un iterable. Ejemplo: lista(agrupados([1,2,3],2)) >>> [(1, 2)] .. cuando usted esperaría [(1,2),(3,)]
    • En el caso especificado en la pregunta, no tendría sentido tener un «incompleto» de la tupla. Si usted quería incluir una incompleta tupla, se podría utilizar izip_longest() en lugar de izip(). E. g: list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0)) –> [(1, 2), (3, 0)]. Espero que esto ayude.
    • Pero para de ser confundido con el grouper receta en la misma documentación. Es definitivamente vale la pena la comprensión de cómo funciona esto—que es cómo usted puede decidir qué hacer con dentado de grupos (omita el resto de los valores, relleno con una fillvalue, o devolver un corto grupo).
    • ¿cómo solucionar su caso?
    • Usted podría utilizar izip_longest().
    • Gracias, pero en mi caso de uso es bastante pequeño. Por lo tanto, estoy usando current, items = items[:25], items[25:] en un bucle while que comprueba len(items)

  2. 168

    Bien, necesita tupla de 2 elementos, por lo que

    data = [1,2,3,4,5,6]
    for i,k in zip(data[0::2], data[1::2]):
        print str(i), '+', str(k), '=', str(i+k)

    Donde:

    • data[0::2] significa crear subconjunto de la colección de elementos que (index % 2 == 0)
    • zip(x,y) crea una tupla de la colección de x y y colecciones mismo índice de elementos.
    • Esto también puede ser ampliado en caso de más de dos elementos que son necesarios. Por ejemplo, for i, j, k in zip(data[0::3], data[1::3], data[2::3]):
    • Mucho más limpio que tirar en una importación y la definición de una función!
    • Pero esto sólo funciona en las secuencias, la función funciona en cualquier iterable; y este utiliza O(N) espacio adicional, la función no; por otro lado, este es generalmente más rápido. Hay buenas razones para escoger una o la otra; el miedo de import no es uno de ellos.
  3. 69
    >>> l = [1,2,3,4,5,6]
    
    >>> zip(l,l[1:])
    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
    
    >>> zip(l,l[1:])[::2]
    [(1, 2), (3, 4), (5, 6)]
    
    >>> [a+b for a,b in zip(l,l[1:])[::2]]
    [3, 7, 11]
    
    >>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
    ['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']
    • Esto no es trabajar en Python-3.6.0 pero se sigue trabajando en Python-2.7.10
    • devuelve un zip objeto en Python 3, que no es subscriptable. Tiene que ser convertido a una secuencia (list, tuple, etc.) en primer lugar, pero «no trabajo» es un poco de un tramo.
  4. 55

    Una solución simple.

    l = [1, 2, 3, 4, 5, 6] 
    
    for i in range(0, len(l), 2): 
    print str(l[i]), '+', str(l[i + 1]), '=', str(l[i] + l[i + 1]) 
    
    • ¿qué pasa si su lista no es ni siquiera, y solo desea mostrar el último número es?
    • no se le. Por favor explicar un poco más.
    • Gracias. Pensé que ya se cómo hacerlo. El problema era que si había una lista en la que no tenía ni la cantidad de números en el mismo, se obtendría un índice de error. Solucionado con un try: excepto:
    • O ((l[i], l[i+1])for i in range(0, len(l), 2)) para un generador, puede ser fácilmente modificado para más tuplas.
  5. 41

    Mientras que todas las respuestas utilizando zip son correctos, me parece que la implementación de la funcionalidad de sí mismo conduce a un código más legible:

    def pairwise(it):
        it = iter(it)
        while True:
            yield next(it), next(it)

    La it = iter(it) parte asegura que it es en realidad un iterador, no sólo un iterable. Si it ya es un iterador, esta línea es un no-op.

    Uso:

    for a, b in pairwise([0, 1, 2, 3, 4, 5]):
        print(a + b)
    • Esta solución permite la generalización de tamaño de tuplas > 2
    • Esta solución también funciona si it es sólo un iterador y no un iterable. Las otras soluciones que parecen depender de la posibilidad de crear dos independientes iteradores para la secuencia.
    • He encontrado este enfoque en stackoverflow.com/a/16815056/2480481 antes de ver esta respuesta. Es más limpio, más fácil de tratar con zip().
    • Me gusta que permite evitar triplicar el uso de la memoria como el aceptado respuesta.
    • Esto no funciona muy bien con for bucles en Python 3.5+, debido a la PEP 479, que sustituye a cualquier StopIteration se crió en un generador con una RuntimeError.
  6. 19

    Espero que esto sea aún más elegante manera de hacerlo.

    a = [1,2,3,4,5,6]
    zip(a[::2], a[1::2])
    
    [(1, 2), (3, 4), (5, 6)]
    • Esto funciona bien con Python 3.6, gracias!
  7. 16

    En caso de que esté interesado en el rendimiento, me hizo una pequeña referencia (usando mi biblioteca simple_benchmark) para comparar el rendimiento de las soluciones y he incluido una función de uno de mis paquetes: iteration_utilities.el mero

    from iteration_utilities import grouper
    import matplotlib as mpl
    from simple_benchmark import BenchmarkBuilder
    
    bench = BenchmarkBuilder()
    
    @bench.add_function()
    def Johnsyweb(l):
        def pairwise(iterable):
            "s -> (s0, s1), (s2, s3), (s4, s5), ..."
            a = iter(iterable)
            return zip(a, a)
    
        for x, y in pairwise(l):
            pass
    
    @bench.add_function()
    def Margus(data):
        for i, k in zip(data[0::2], data[1::2]):
            pass
    
    @bench.add_function()
    def pyanon(l):
        list(zip(l,l[1:]))[::2]
    
    @bench.add_function()
    def taskinoor(l):
        for i in range(0, len(l), 2):
            l[i], l[i+1]
    
    @bench.add_function()
    def mic_e(it):
        def pairwise(it):
            it = iter(it)
            while True:
                try:
                    yield next(it), next(it)
                except StopIteration:
                    return
    
        for a, b in pairwise(it):
            pass
    
    @bench.add_function()
    def MSeifert(it):
        for item1, item2 in grouper(it, 2):
            pass
    
    bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
    benchmark_result = bench.run()
    mpl.rcParams['figure.figsize'] = (8, 10)
    benchmark_result.plot_both(relative_to=MSeifert)

    Iterar sobre todos los dos elementos en una lista

    Así que si quieres la solución más rápida sin dependencias externas que probablemente sólo debe utilizar el enfoque dado por Johnysweb (en el momento de la escritura es el más upvoted y aceptado respuesta).

    Si no te importa la dependencia adicional, a continuación, el grouper de iteration_utilities probablemente será un poco más rápido.

    Pensamientos adicionales

    Algunos de los enfoques tienen algunas restricciones, que no han sido discutidos aquí.

    Por ejemplo un par de soluciones sólo funcionan para las secuencias (que son las listas, cadenas, etc.), por ejemplo Margus/pyanon/taskinoor soluciones que utiliza la indexación, mientras que otras soluciones de trabajo en cualquier iterable (que es de las secuencias de y generadores, los iteradores) como Johnysweb/mic_e/mis soluciones.

    Luego Johnysweb también proporcionó una solución que funciona para otros tamaños de 2, mientras que las otras respuestas no (bueno, la iteration_utilities.grouper también permite establecer el número de elementos a «grupo»).

    Luego está también la pregunta acerca de qué debe ocurrir si hay un número impar de elementos en la lista. Si el resto de la partida ser despedido? Si la lista se rellena para que sea aún de tamaño? Si el resto de la partida se volvió como una sola? La otra respuesta no abordar este punto directamente, sin embargo si no he pasado por alto algo que todas siguen el criterio de que el resto de la partida debe ser desestimado (excepto para taskinoors respuesta – que en realidad provoca una Excepción).

    Con grouper usted puede decidir lo que desea hacer:

    >>> from iteration_utilities import grouper
    
    >>> list(grouper([1, 2, 3], 2))  # as single
    [(1, 2), (3,)]
    
    >>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
    [(1, 2)]
    
    >>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
    [(1, 2), (3, None)]
  8. 11

    Utilizar el zip y iter comandos juntos:

    Puedo encontrar esta solución con iter a ser muy elegante:

    it = iter(l)
    list(zip(it, it))
    # [(1, 2), (3, 4), (5, 6)]

    Que he encontrado en la Python 3 código postal de la documentación.

    it = iter(l)
    print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')
    
    # 1 + 2 = 3
    # 3 + 4 = 7
    # 5 + 6 = 11

    A generalizar a N elementos a la vez:

    N = 2
    list(zip(*([iter(l)] * N)))
    # [(1, 2), (3, 4), (5, 6)]
  9. 9
    for (i, k) in zip(l[::2], l[1::2]):
        print i, "+", k, "=", i+k

    zip(*iterable) devuelve una tupla con el siguiente elemento de cada iterable.

    l[::2] devuelve la 1ª, la 3ª, la 5ª, etc. elemento de la lista: el punto y coma indica que el sector comienza al principio porque no hay ningún número que está detrás de la segunda colon sólo es necesario si desea un ‘paso en el sector (en este caso 2).

    l[1::2] hace lo mismo pero se inicia en el segundo elemento de la lista y devuelve la 2ª, la 4ª, 6ª, etc. elemento de la original lista.

  10. 1

    Para la persona que lo puede ayudar, aquí es una solución a un problema similar pero con la superposición de los pares (en lugar de la que se excluyen mutuamente pares).

    De Python itertools documentación:

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

    O, más en general:

    from itertools import izip
    
    def groupwise(iterable, n=2):
        "s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
        t = tee(iterable, n)
        for i in range(1, n):
            for j in range(0, i):
                next(t[i], None)
        return izip(*t)
  11. 1

    Necesito para dividir una lista con un número y se fija como este.

    l = [1,2,3,4,5,6]
    
    def divideByN(data, n):
            return [data[i*n : (i+1)*n] for i in range(len(data)//n)]  
    
    >>> print(divideByN(l,2))
    [[1, 2], [3, 4], [5, 6]]
    
    >>> print(divideByN(l,3))
    [[1, 2, 3], [4, 5, 6]]
  12. 0

    Pensado que este es un buen lugar para compartir mis generalización de este n>2, que es sólo una ventana de desplazamiento de más de un iterable:

    def sliding_window(iterable, n):
        its = [ itertools.islice(iter, i, None) 
                for i, iter
                in enumerate(itertools.tee(iterable, n)) ]                               
    
        return itertools.izip(*its)
  13. 0

    El título de esta pregunta es engañosa, parecen estar buscando pares consecutivos, pero si usted desea iterar sobre el conjunto de todos los posibles pares de esto va a funcionar :

    for i,v in enumerate(items[:-1]):
            for u in items[i+1:]:
  14. 0

    El uso de escribir así que usted puede comprobar los datos mediante mypy herramienta de análisis estático:

    from typing import Iterator, Any, Iterable, TypeVar, Tuple
    
    T_ = TypeVar('T_')
    Pairs_Iter = Iterator[Tuple[T_, T_]]
    
    def legs(iterable: Iterator[T_]) -> Pairs_Iter:
        begin = next(iterable)
        for end in iterable:
            yield begin, end
            begin = end
  15. 0

    Un enfoque simplista:

    [(a[i],a[i+1]) for i in range(0,len(a),2)]

    esto es útil si su matriz es una y desea iterar sobre ella por pares.
    Para iterar sobre trillizos o más, sólo cambia el «rango» de paso de comando, por ejemplo:

    [(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]

    (usted tiene que tratar con el exceso de los valores si su longitud de matriz y el paso no se ajustan a)

  16. -1

    Aquí podemos tener alt_elem método que puede caber en su bucle for.

    def alt_elem(list, index=2):
        for i, elem in enumerate(list, start=1):
            if not i % index:
               yield tuple(list[i-index:i])
    
    
    a = range(10)
    for index in [2, 3, 4]:
        print("With index: {0}".format(index))
        for i in alt_elem(a, index):
           print(i)

    De salida:

    With index: 2
    (0, 1)
    (2, 3)
    (4, 5)
    (6, 7)
    (8, 9)
    With index: 3
    (0, 1, 2)
    (3, 4, 5)
    (6, 7, 8)
    With index: 4
    (0, 1, 2, 3)
    (4, 5, 6, 7)

    Nota: por Encima de la solución podría no ser eficiente, considerando las operaciones realizadas en func.

  17. -1
    a_list = [1,2,3,4,5,6]
    empty_list = [] 
    for i in range(0,len(a_list),2):
       empty_list.append(a_list[i]+a_list[i+1])   
    print(empty_list)

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea