Weź zawartość listy i dołącz ją do innej listy

193

Próbuję zrozumieć, czy sensowne jest przeniesienie zawartości listy i dołączenie jej do innej listy.

Mam pierwszą listę utworzoną za pomocą funkcji pętli, która pobierze określone wiersze z pliku i zapisze je na liście.

Następnie używana jest druga lista, aby zapisać te linie i rozpocząć nowy cykl na innym pliku.

Moim pomysłem było pobranie listy po zakończeniu cyklu for, zrzucenie jej na drugą listę, a następnie rozpoczęcie nowego cyklu, zrzucenie zawartości pierwszej listy ponownie do drugiej, ale dołączenie, aby druga lista była suma wszystkich mniejszych plików list utworzonych w mojej pętli. Lista musi być dołączona tylko wtedy, gdy spełnione są określone warunki.

Wygląda to podobnie do tego:

# 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

Czy to ma sens, czy powinienem wybrać inną trasę?

Potrzebuję czegoś wydajnego, co nie zajęłoby zbyt wielu cykli, ponieważ lista dzienników jest długa, a każdy plik tekstowy jest dość duży; więc pomyślałem, że listy pasują do celu.

użytkownik1006198
źródło

Odpowiedzi:

371

Prawdopodobnie chcesz

list2.extend(list1)

zamiast

list2.append(list1)

Oto różnica:

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

Ponieważ list.extend()akceptuje dowolną iterowalność, możesz również zastąpić

for line in mylog:
    list1.append(line)

przez

list1.extend(mylog)
Sven Marnach
źródło
Tak, append jest dla jednego elementu, ext jest jak konkat.
Catalina Chircu
13

Spójrz na itertools.chain, aby szybko traktować wiele małych list jako pojedynczą dużą listę (lub przynajmniej jako jedną dużą iterowalną) bez kopiowania mniejszych list:

>>> 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
źródło
To brzmi naprawdę fajnie! Spojrzę na to, aby sprawdzić, czy mogę zastąpić kod, który już mam za pomocą itertools!
user1006198,
3

To wydaje się dość rozsądne w przypadku tego, co próbujesz zrobić.

Nieco krótsza wersja, która opiera się na Pythonie, aby wykonać więcej ciężkich zadań, może być:

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

    ....

W (True for line in list1 if "string" in line)iteracje nad listi emituje Truegdy zostanie znaleziony. any()używa oceny zwarcia, aby powrócić, Truegdy tylko pierwszy Trueelement zostanie znaleziony. list2.extend()dołącza zawartość list1do końca.

Kirk Strauser
źródło
1
any(True for line in list1 if "string" in line)jest bardziej starannie napisany jako any("string" in line for line in list1).
Karl Knechtel
Dobra uwaga, @KarlKnechtel, chociaż są one nieco inne. Twoja wersja zawsze emituje coś , Prawda lub Fałsz. Mój emituje tylko jedną Prawdę. Nie mam pojęcia, jak wypadają te testy porównawcze ani czy jest wystarczająca różnica, aby w ogóle mieć znaczenie.
Kirk Strauser
W obu przypadkach anyotrzymuje generator; nigdzie nie jest budowana lista wartości Prawda lub Fałsz. Moja wersja zwraca więcej rzeczy anydo sprawdzenia, ale w zamian za niezrobienie tego samego sprawdzenia w samym generatorze. Wyobrażam sobie, że to pranie, ale timeittutaj jest autorytatywne, nie ja. :)
Karl Knechtel
3

Możesz także łączyć dwie listy (powiedz a, b) za pomocą operatora „+”. Na przykład,

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
źródło
3

Podsumowując poprzednie odpowiedzi. Jeśli masz listę z [0,1,2]drugą [3,4,5]i chcesz je scalić, tak się [0,1,2,3,4,5]stanie, możesz albo użyć, chainingalbo extendingpowinieneś znać różnice, aby mądrze z niej korzystać dla swoich potrzeb.

Rozszerzanie listy

Za pomocą metody listklas extendmożesz wykonać kopię elementów z jednej listy na drugą. Spowoduje to jednak dodatkowe zużycie pamięci, co powinno być w większości przypadków w porządku, ale może powodować problemy, jeśli chcesz być wydajnym.

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

wprowadź opis zdjęcia tutaj

Łańcuch listy

Przeciwnie, możesz użyć itertools.chaindo połączenia wielu list, które zwrócą tak zwane, iteratorktóre można wykorzystać do iteracji po listach. Jest to bardziej wydajne pod względem pamięci, ponieważ nie kopiuje elementów, ale po prostu wskazuje następną listę.

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

wprowadź opis zdjęcia tutaj

Stwórz iterator, który zwraca elementy od pierwszej iteracji, aż do wyczerpania, a następnie przechodzi do następnej iteracji, aż wszystkie iteracje zostaną wyczerpane. Służy do traktowania kolejnych sekwencji jako pojedynczej sekwencji.

użytkownik1767754
źródło
2

Używanie map()i reduce()wbudowanych funkcji

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)

Minimalne „do zapętlenia” i elegancki wzór kodowania :)

pX0r
źródło
0

Jeśli mamy listę jak poniżej:

list  = [2,2,3,4]

dwa sposoby skopiowania go na inną listę.

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
źródło