Tome el contenido de una lista y agréguelo a otra lista


191

Estoy tratando de entender si tiene sentido tomar el contenido de una lista y agregarlo a otra lista.

Tengo la primera lista creada a través de una función de bucle, que obtendrá líneas específicas de un archivo y las guardará en una lista.

Luego, se utiliza una segunda lista para guardar estas líneas e iniciar un nuevo ciclo sobre otro archivo.

Mi idea era obtener la lista una vez que se realiza el ciclo for, volcarla en la segunda lista, luego comenzar un nuevo ciclo, volcar el contenido de la primera lista nuevamente en la segunda pero agregarla, por lo que la segunda lista será la suma de todos los archivos de lista más pequeños creados en mi bucle. La lista debe agregarse solo si se cumplen ciertas condiciones.

Se parece a algo similar a esto:

# This is done for each log in my directory, i have a loop running
for logs in mydir:

    for line in mylog:
        #...if the conditions are met
        list1.append(line)

    for item in list1:
        if "string" in item: #if somewhere in the list1 i have a match for a string
            list2.append(list1) # append every line in list1 to list2
            del list1 [:] # delete the content of the list1
            break
        else:
            del list1 [:] # delete the list content and start all over

¿Tiene sentido o debo ir por una ruta diferente?

Necesito algo eficiente que no tome muchos ciclos, ya que la lista de registros es larga y cada archivo de texto es bastante grande; Así que pensé que las listas se adaptarían al propósito.

Respuestas:


369

Probablemente quieras

list2.extend(list1)

en vez de

list2.append(list1)

Aquí está la diferencia:

>>> a = range(5)
>>> b = range(3)
>>> c = range(2)
>>> b.append(a)
>>> b
[0, 1, 2, [0, 1, 2, 3, 4]]
>>> c.extend(a)
>>> c
[0, 1, 0, 1, 2, 3, 4]

Como list.extend()acepta un iterativo arbitrario, también puede reemplazar

for line in mylog:
    list1.append(line)

por

list1.extend(mylog)

Sí, agregar es para un elemento, extender es como concat.
Catalina Chircu

13

Eche un vistazo a itertools.chain para ver una forma rápida de tratar muchas listas pequeñas como una sola lista grande (o al menos como una única lista grande iterable) sin copiar las listas más pequeñas:

>>> import itertools
>>> p = ['a', 'b', 'c']
>>> q = ['d', 'e', 'f']
>>> r = ['g', 'h', 'i']
>>> for x in itertools.chain(p, q, r):
        print x.upper()

Eso suena muy hábil! ¡Lo echaré un vistazo para ver si puedo reemplazar el código que ya tengo usando itertools!
user1006198

3

Eso parece bastante razonable para lo que estás tratando de hacer.

Una versión un poco más corta que se apoya en Python para hacer más trabajo pesado podría ser:

for logs in mydir:

    for line in mylog:
        #...if the conditions are met
        list1.append(line)

    if any(True for line in list1 if "string" in line):
        list2.extend(list1)
    del list1

    ....

El (True for line in list1 if "string" in line)itera listy emite Truecada vez que se encuentra una coincidencia. any()utiliza la evaluación de cortocircuito para regresar Truetan pronto como se encuentre el primer Trueelemento. list2.extend()añade el contenido de list1al final.


1
any(True for line in list1 if "string" in line)está más claramente escrito como any("string" in line for line in list1).
Karl Knechtel

Buen punto, @KarlKnechtel, aunque son sutilmente diferentes. Su versión siempre emite algo , ya sea verdadero o falso. El mío solo emite un solo Verdadero. No tengo idea de cómo se comparan, o si hay suficiente diferencia para importar.
Kirk Strauser el

En ambos casos, anyrecibe un generador; no se construye ninguna lista de valores verdaderos o falsos en ningún lado. Mi versión devuelve más cosas para anyverificar, pero a cambio de no hacer la misma verificación en el generador. Me imagino que es un lavado, pero timeitaquí tiene autoridad, no yo. :)
Karl Knechtel

3

También puede combinar dos listas (digamos a, b) usando el operador '+'. Por ejemplo,

a = [1,2,3,4]
b = [4,5,6,7]
c = a + b

Output:
>>> c
[1, 2, 3, 4, 4, 5, 6, 7]

3

Para recapitular sobre las respuestas anteriores. Si tiene una lista con [0,1,2]y otra con [3,4,5]y desea fusionarlas, entonces se convierte en [0,1,2,3,4,5], puede usar chainingoextending debe conocer las diferencias para usarlo sabiamente para sus necesidades.

Extendiendo una lista

Usando el método de listclases extend, puede hacer una copia de los elementos de una lista a otra. Sin embargo, esto causará un uso de memoria adicional, que debería estar bien en la mayoría de los casos, pero podría causar problemas si desea ser eficiente en la memoria.

a = [0,1,2]
b = [3,4,5]
a.extend(b)
>>[0,1,2,3,4,5]

ingrese la descripción de la imagen aquí

Encadenando una lista

Al contrario, puede usar itertools.chainpara conectar muchas listas, lo que devolverá un llamado iteratorque se puede usar para iterar sobre las listas. Esto es más eficiente en cuanto a memoria, ya que no está copiando elementos sino simplemente apuntando a la siguiente lista.

import itertools
a = [0,1,2]
b = [3,4,5]
c = itertools.chain(a, b)

ingrese la descripción de la imagen aquí

Haga un iterador que devuelva elementos del primer iterable hasta que se agote, luego pase al siguiente iterable, hasta que se agoten todos los iterables. Se usa para tratar secuencias consecutivas como una secuencia única.


2

Utilizando el map()y reduce()funciones incorporadas

def file_to_list(file):
     #stuff to parse file to a list
     return list

files = [...list of files...]

L = map(file_to_list, files)

flat_L = reduce(lambda x,y:x+y, L)

Mínimo "para bucle" y elegante patrón de codificación :)


0

Si tenemos una lista como la siguiente:

list  = [2,2,3,4]

dos formas de copiarlo en otra lista.

1)

x = [list]  # x =[] x.append(list) same 
print("length is {}".format(len(x)))
for i in x:
    print(i)
length is 1
[2, 2, 3, 4]

2)

x = [l for l in list]
print("length is {}".format(len(x)))
for i in x:
    print(i)
length is 4
2
2
3
4
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.