Prendi il contenuto di un elenco e aggiungilo a un altro elenco


193

Sto cercando di capire se ha senso prendere il contenuto di un elenco e aggiungerlo a un altro elenco.

Ho il primo elenco creato tramite una funzione loop, che otterrà linee specifiche da un file e le salverà in un elenco.

Quindi viene utilizzato un secondo elenco per salvare queste righe e avviare un nuovo ciclo su un altro file.

La mia idea era di ottenere l'elenco una volta che il ciclo for è terminato, scaricarlo nel secondo elenco, quindi avviare un nuovo ciclo, scaricare nuovamente il contenuto del primo elenco nel secondo ma aggiungendolo, quindi il secondo elenco sarà il somma di tutti i file di elenco più piccoli creati nel mio loop. L'elenco deve essere aggiunto solo se sono soddisfatte determinate condizioni.

Sembra qualcosa di simile a questo:

# 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

Ha senso o dovrei seguire un percorso diverso?

Ho bisogno di qualcosa di efficiente che non richiederebbe troppi cicli, poiché l'elenco dei registri è lungo e ogni file di testo è piuttosto grande; quindi ho pensato che le liste si sarebbero adattate allo scopo.

Risposte:


371

Probabilmente vuoi

list2.extend(list1)

invece di

list2.append(list1)

Ecco la differenza:

>>> 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]

Poiché list.extend()accetta un iterabile arbitrario, puoi anche sostituirlo

for line in mylog:
    list1.append(line)

di

list1.extend(mylog)

Sì, append è per un elemento, extender è come concat.
Catalina Chircu,

13

Dai un'occhiata a itertools.chain per un modo rapido di trattare molti piccoli elenchi come un unico grande elenco (o almeno come un unico grande iterabile) senza copiare gli elenchi più piccoli:

>>> 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()

Sembra davvero perfetto! Lo guarderò per vedere se posso sostituire il codice che ho già usando itertools!
user1006198

3

Sembra abbastanza ragionevole per quello che stai cercando di fare.

Una versione leggermente più corta che si appoggia su Python per fare di più del sollevamento pesante potrebbe essere:

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

    ....

Si (True for line in list1 if "string" in line)ripete listed emette Trueogni volta che viene trovata una corrispondenza. any()utilizza la valutazione del corto circuito per tornare Truenon appena Trueviene trovato il primo elemento. list2.extend()accoda il contenuto list1alla fine.


1
any(True for line in list1 if "string" in line)è scritto più ordinatamente come any("string" in line for line in list1).
Karl Knechtel,

Buon punto, @KarlKnechtel, anche se sono leggermente diversi. La tua versione emette sempre qualcosa , True o False. Il mio emette solo un vero True. Non ho idea di come escano questi benchmark, o se ci sia abbastanza differenza da considerare.
Kirk Strauser,

In entrambi i casi, anyriceve un generatore; nessun elenco di valori Vero o Falso è costruito da nessuna parte. La mia versione restituisce più cose anyda controllare, ma in cambio non fa lo stesso controllo nel generatore stesso. Immagino sia un lavaggio, ma timeitqui è autorevole, non io. :)
Karl Knechtel,

3

Puoi anche combinare due liste (diciamo a, b) usando l'operatore '+'. Per esempio,

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

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

3

Ricapitolando le risposte precedenti. Se hai un elenco con [0,1,2]un altro con [3,4,5]e vuoi unirli, così diventa [0,1,2,3,4,5], puoi usare chainingo extendinge dovresti conoscere le differenze per usarlo saggiamente per le tue esigenze.

Estensione di un elenco

Utilizzando il metodo delle listclassi extend, è possibile eseguire una copia degli elementi da un elenco a un altro. Tuttavia, ciò causerà un ulteriore utilizzo della memoria, che dovrebbe andare bene nella maggior parte dei casi, ma potrebbe causare problemi se si desidera essere efficienti nella memoria.

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

inserisci qui la descrizione dell'immagine

Concatenare un elenco

Al contrario è possibile utilizzare itertools.chainper collegare molti elenchi, che restituiranno un cosiddetto iteratorche può essere utilizzato per scorrere tra gli elenchi. Questo è più efficiente in termini di memoria in quanto non sta copiando elementi ma semplicemente puntando all'elenco successivo.

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

inserisci qui la descrizione dell'immagine

Crea un iteratore che restituisce elementi dal primo iterabile fino all'esaurimento, quindi procede al successivo iterabile, fino a quando tutti gli iterabili sono esauriti. Utilizzato per il trattamento di sequenze consecutive come un'unica sequenza.


2

Utilizzando l' map()e reduce()funzioni built-in

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)

Minimo "per looping" ed elegante schema di codifica :)


0

Se abbiamo un elenco come di seguito:

list  = [2,2,3,4]

due modi per copiarlo in un altro elenco.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.