2011-11-18 16 views
114

Próbuję zrozumieć, czy warto wziąć zawartość listy i dołączyć ją do innej listy.Python: weź zawartość listy i dołącz ją do innej listy.

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

Następnie druga lista jest używana do zapisania tych linii i rozpoczęcia nowego cyklu nad innym plikiem.

Mój pomysł polegał na tym, aby uzyskać listę raz, gdy cykl jest zakończony, zrzucić go na drugą listę, a następnie rozpocząć nowy cykl, ponownie zrzucić zawartość pierwszej listy do drugiej, ale dołączając ją, tak aby druga lista będzie sumą wszystkich mniejszych plików list utworzonych w mojej pętli. Lista musi być dołączona tylko wtedy, gdy spełnione są określone warunki.

To wygląda jak coś podobnego 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 mam iść na inną drogą?

Potrzebuję czegoś wydajnego, które nie zajmie 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 będą pasować do celu.

Odpowiedz

220

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] 

Od list.extend() akceptuje dowolną iterable, można również zastąpić

for line in mylog: 
    list1.append(line) 

przez

list1.extend(mylog) 
9

Spójrz na itertools.chain na szybki sposób leczenia wielu małych list jako jeden duży listy (lub przynajmniej jako jeden wielki iterable) 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() 
+0

To brzmi naprawdę śliskie! Rzucę okiem na to, aby sprawdzić, czy mogę zastąpić kod, który już używam itertools! – user1006198

3

To wydaje się dość uzasadnione, co próbujesz zrobić.

Nieco krótsza wersja, która opiera się na Pythonie zrobić więcej z podnoszenia ciężkich 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 

    .... 

The (True for line in list1 if "string" in line) iteracje nad list i emituje True gdy zostanie znaleziony. any() używa oceny zwarcia do zwrócenia True, gdy tylko zostanie znaleziony pierwszy element True. list2.extend() dołącza do końca zawartość list1.

+0

Dzięki za wskazanie, że optymalizacja Kirk! – user1006198

+1

'any (True dla linii na liście 1, jeśli" string "w linii)' jest starannie napisane jako 'any (" string "w linii dla linii na liście1)'. –

+0

Dobra uwaga, @KarlKnechtel, chociaż są one subtelnie różne. Twoja wersja zawsze wysyła * coś *, True lub False. Mój emituje tylko jedną True. Nie mam pojęcia, jak te testy porównawcze się sprawdzają, ani czy w ogóle istnieje wystarczająca różnica. –

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) 

Minimal "do pętli" i elegancki wzór kodujący :)

0

Przypomnę na poprzednich odpowiedzi. Jeśli masz listę z [0,1,2] i inną z [3,4,5] i chcesz je scalić, to staje się [0,1,2,3,4,5], możesz użyć chaining lub extending i powinien znać różnice, aby mądrze go używać do swoich potrzeb.

Rozszerzanie listy

Używanie list klas extend metody, można zrobić kopię elementów z jednej listy na drugą. Jednak spowoduje to dodatkowe zużycie pamięci, co w większości przypadków powinno być w porządku, ale może powodować problemy, jeśli chcesz zachować wydajność pamięci.

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

enter image description here

Chaining listę

Wbrew można użyć itertools.chain drut wiele list, który powróci tzw iterator który może być używany do iteracji na listach. Jest to bardziej wydajne pod względem pamięci, ponieważ nie kopiuje elementów, a jedynie wskazuje na następną listę.

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

enter image description here

Złóż iterator, który zwraca elementy z pierwszej iterable dopóki nie zostanie wyczerpany, a następnie przechodzi do następnego iterable, aż wszystkie iterables są wyczerpane. Używany do leczenia kolejnych sekwencji jako pojedynczej sekwencji.

0

Jeśli mamy listę jak poniżej:

list = [2,2,3,4] 

dwa sposoby, aby skopiować go do innej listy.

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