Pegue o conteúdo de uma lista e anexe-o a outra lista

191

Estou tentando entender se faz sentido pegar o conteúdo de uma lista e anexá-lo a outra lista.

Eu tenho a primeira lista criada através de uma função de loop, que obterá linhas específicas de um arquivo e as salvará em uma lista.

Em seguida, uma segunda lista é usada para salvar essas linhas e iniciar um novo ciclo sobre outro arquivo.

Minha idéia era obter a lista assim que o ciclo for terminar, despejá-lo na segunda lista e iniciar um novo ciclo, despejar o conteúdo da primeira lista novamente na segunda, mas anexá-la, para que a segunda lista seja a soma de todos os arquivos de lista menores criados no meu loop. A lista deve ser anexada apenas se determinadas condições forem atendidas.

Parece algo semelhante a este:

# 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

Isso faz sentido ou devo seguir uma rota diferente?

Preciso de algo eficiente que não ocupe muitos ciclos, pois a lista de logs é longa e cada arquivo de texto é bastante grande; então pensei que as listas se encaixariam no objetivo.

user1006198
fonte

Respostas:

369

Você provavelmente quer

list2.extend(list1)

ao invés de

list2.append(list1)

Aqui está a diferença:

>>> 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()aceita um iterável arbitrário, você também pode substituir

for line in mylog:
    list1.append(line)

de

list1.extend(mylog)
Sven Marnach
fonte
Sim, acrescentar é para um elemento, estender é como concat.
Catalina Chircu
13

Dê uma olhada no itertools.chain para uma maneira rápida de tratar muitas listas pequenas como uma única lista grande (ou pelo menos como uma única iterável grande) sem copiar as listas menores:

>>> 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()
Raymond Hettinger
fonte
Isso soa muito bem! Vou dar uma olhada para ver se consigo substituir o código que já tenho usando o itertools!
user1006198
3

Isso parece bastante razoável para o que você está tentando fazer.

Uma versão ligeiramente mais curta, que se apóia no Python para fazer mais trabalho pesado, pode 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

    ....

Ele (True for line in list1 if "string" in line)itera liste emite Truesempre que uma correspondência é encontrada. any()usa a avaliação de curto-circuito para retornar Trueassim que o primeiro Trueelemento for encontrado. list2.extend()anexa o conteúdo de list1até o final.

Kirk Strauser
fonte
1
any(True for line in list1 if "string" in line)está escrito mais ordenadamente como any("string" in line for line in list1).
precisa
Bom ponto, @KarlKnechtel, embora sejam sutilmente diferentes. Sua versão sempre emite algo , Verdadeiro ou Falso. O meu emite apenas um único True. Não tenho idéia de como essas referências se referem, ou se há diferença suficiente para importar.
precisa
Nos dois casos, anyrecebe um gerador; nenhuma lista de valores Verdadeiro ou Falso é construída em qualquer lugar. Minha versão retorna mais coisas para anyverificar, mas em troca de não fazer a mesma verificação no próprio gerador. Eu imagino que é uma lavagem, mas timeité autoritário aqui, não eu. :)
Karl Knechtel
3

Você também pode combinar duas listas (digamos a, b) usando o operador '+'. Por exemplo,

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

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

Para recapitular as respostas anteriores. Se você tem uma lista com[0,1,2] e outra com [3,4,5]e deseja mesclá-las, então ela se torna [0,1,2,3,4,5], você pode usar chainingou extendinge deve conhecer as diferenças para usá-la sabiamente para suas necessidades.

Estendendo uma lista

Usando o método de listclasses extend, você pode fazer uma cópia dos elementos de uma lista para outra. No entanto, isso causará uso de memória extra, o que deve ser bom na maioria dos casos, mas pode causar problemas se você quiser ter eficiência de memória.

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

insira a descrição da imagem aqui

Encadeando uma lista

Ao contrário, você pode usar itertools.chainpara conectar muitas listas, que retornarão uma chamada iteratorque pode ser usada para iterar nas listas. Isso é mais eficiente em termos de memória, pois não está copiando elementos, mas apenas apontando para a próxima lista.

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

insira a descrição da imagem aqui

Crie um iterador que retorne elementos da primeira iterável até que esteja esgotado e prossiga para a próxima iterável, até que todos os iteráveis ​​estejam esgotados. Usado para tratar sequências consecutivas como uma única sequência.

user1767754
fonte
2

Usando as funções map()e reduce()internas

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 loop" e padrão de codificação elegante :)

pX0r
fonte
0

Se tivermos lista como abaixo:

list  = [2,2,3,4]

duas maneiras de copiá-lo para outra 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
Avinash
fonte