Tengo una lista en la que algunos de los artículos deberá ser trasladado en una lista separada (por una función de comparación). Esos elementos son pura dicts. La pregunta es ¿cómo debo iterar sobre la lista.

Cuando se itera la forma más sencilla, for element in mylist, entonces no sé el índice del elemento. No hay .iteritems() métodos de las listas, lo cual podría ser útil aquí. Así que he intentado utilizar for index in range(len(mylist)):, que [1] parece demasiado complicado como para python y [2] no me satisface, ya que range(len()) se calcula una sola vez en el principio, y si puedo eliminar un elemento de la lista durante la iteración, voy a llegar IndexError: list index out of range.

Finalmente, mi pregunta es ¿cómo debo recorrer una lista de python, para ser capaz de eliminar elementos de la lista (mediante una función de comparación y ponerlos en otra lista)?

  • Así pues, usted quiere terminar con la lista original que falta un número de elementos, y una nueva lista que contiene los elementos eliminados?
  • exactamente
  • FYI uso .los elementos() en Python 3.x.
InformationsquelleAutor ducin | 2014-02-22

6 Comentarios

  1. 1

    La creación de una nueva lista realmente no es mucho de un problema en comparación con la eliminación de elementos de la antigua. Del mismo modo, repitiendo dos veces es una muy menor impacto en el rendimiento, probablemente abrumado por otros factores. A menos que tenga una muy buena razón para hacer lo contrario, respaldado por crear el perfil de tu código, te recomiendo recorrer dos veces y la construcción de dos nuevas listas:

    from itertools import ifilter, ifilterfalse
    
    l1 = list(ifilter(condition, l))
    l2 = list(ifilterfalse(condition, l))

    Usted puede cortar-asignar el contenido de una de las nuevas listas en el original si desea:

    l[:] = l1

    Si usted está absolutamente seguro de que quieres un 1 paso de la solución, y estás absolutamente seguro de que desea modificar de la lista original en lugar en lugar de crear una copia, los siguientes evita cuadrática golpes de rendimiento de popping desde el medio de una lista:

    j = 0
    l2 = []
    for i in range(len(l)):
        if condition(l[i]):
            l[j] = l[i]
            j += 1
        else:
            l2.append(l[i])
    del l[j:]

    Nos movemos cada elemento de la lista directamente a su posición final sin perder tiempo cambiando los elementos que realmente no necesita ser cambiado. Podríamos utilizar for item in l si queríamos, y que probablemente iba a ser un poco más rápido, pero cuando el algoritmo implica la modificación de la cosa que estamos iterando, yo prefiero el índice explícita.

  2. 2

    Usted puede utilizar para enumerar función y realizar una copia temporal de la lista:

    for i, value in enumerate(old_list[:]):
       # i == index
       # value == dictionary
       # you can safely remove from old_list because we are iterating over copy
  3. 1

    Prefiero no tocar el original de la lista y hacer como @Martol1ni, pero una manera de hacerlo en su lugar y no ser afectado por la eliminación de elementos sería para recorrer hacia atrás:

    for i in reversed(range(len()):
        # do the filtering...

    Que sólo afecta a los índices de los elementos que se han probado y/o eliminado ya

  4. 1

    Pruebe el comando filtro, y puede invalidar la lista original con demasiado si usted no lo necesita.

    def cmp(i): #Comparator function returning a boolean for a given item
        ...
    
    # mylist is the initial list
    mylist = filter(cmp, mylist)

    mylist ahora es un generador de elementos adecuados. Usted puede utilizar list(mylist) si necesita utilizar más de una vez.

  5. 1

    No lo he probado todavía, pero.. voy a darle un rápido disparo:

    new_list = [old.pop(i) for i, x in reversed(list(enumerate(old))) if comparator(x)]
    • Dejando por 10 minutos, estará de regreso pronto
    • reversed obras en las secuencias de (lo que un enumerate objeto no es)
    • Uso reversed(list(enumerate(old))) y ya está bueno para ir. Impresionante solución +1.
    • Gracias 🙂
    • Tenga en cuenta que las listas no pop de manera muy eficiente, por lo que esta es susceptible de crear un montón de nuevas listas de detrás de las escenas. A menos que la lista es muy larga, esto puede no ser un problema en la práctica, por supuesto.
    • Ah, sí que he notado. Depende de la versión de python que usted está utilizando, sin embargo, y el OP no lo mencionamos.
    • Gracias por la nota! Totalmente de acuerdo, yo no recomendaría a una solución para listas más largas. Las cosas son mucho más difíciles cuando son grandes..
    • Bleh. Oculto cuadrática de la complejidad no es un buen negocio para iterar sobre la entrada de una vez.
    • Yo loled. Me di cuenta de que es muy cierto. Creo que Ricardo solución es mejor en ese sentido :))

  6. 0

    Usted puede hacer esto, podría ser una línea demasiado bien.

    new_list1 = [x for x in old_list if your_comparator(x)]
    new_list2 = [x for x in old_list if x not in new_list1]
    • Estás en la creación de dos nuevas listas y repetir dos veces. Estoy buscando una solución para iterar una vez y mover elementos en la otra lista (por ejemplo,l2.append(l1.pop(ind)))
    • Yo soy, simplemente, va a referirse a @alKids solución. No se puede pedir mucho más limpio.

Dejar respuesta

Please enter your comment!
Please enter your name here