Łączenie w pary elementów listy


82

Wiem, że listę można połączyć w jeden długi ciąg, jak w:

x = ['a', 'b', 'c', 'd']
print ''.join(x)

Oczywiście dałoby to:

'abcd'

Jednak próbuję po prostu połączyć pierwszy i drugi ciąg na liście, a następnie dołączyć trzeci i czwarty i tak dalej. Krótko mówiąc, z powyższego przykładu uzyskamy wynik:

['ab', 'cd']

Czy jest na to prosty sposób? Powinienem również wspomnieć, że długości łańcuchów na liście będą nieprzewidywalne, podobnie jak liczba ciągów na liście, chociaż liczba ciągów zawsze będzie parzysta. Tak więc oryginalna lista mogłaby równie dobrze wyglądać:

['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'] 

„Powinienem chyba również wspomnieć, że długości ciągów na liście będą nieprzewidywalne” - Czy więc długość ma znaczenie? To znaczy, czy chcesz po prostu dołączyć do każdej pary elementów listy, czy faktycznie chcesz spojrzeć na zawartość i dołączyć, o ile wynikowy element pozostaje poniżej specjalnego limitu długości?
poke

po prostu dołącz do każdej pary, pomyślałem, że brak znajomości liczby par może być problemem
John

Odpowiedzi:


76

Możesz użyć notacji plasterków z krokami:

>>> x = "abcdefghijklm"
>>> x[0::2] #0. 2. 4...
'acegikm'
>>> x[1::2] #1. 3. 5 ..
'bdfhjl'
>>> [i+j for i,j in zip(x[::2], x[1::2])] # zip makes (0,1),(2,3) ...
['ab', 'cd', 'ef', 'gh', 'ij', 'kl']

Ta sama logika dotyczy również list. Długość łańcucha nie ma znaczenia, ponieważ po prostu dodajesz do siebie dwa ciągi.


1
Nie ma wątpliwości, że odpowiedź Kevpie jest znacznie lepsza. W tym x[:::2]tworzy obiekt, x[1::2]tworzy inny obiekt, te kreacje są prawdopodobnie oparte na obliczaniu indeksów pod maską, a wywołanie funkcji z tymi dwoma obiektami przekazanymi jako argumenty jest konieczne, zanim będzie można uzyskać kolejne pary elementów które muszą być połączone. Podczas gdy w odpowiedzi kevpie istnieje tylko utworzenie jednego iteratora, a następnie iteracja przeskakuje od elementu do elementu nienaruszonej listy bez konieczności zajmowania się indeksami, a to jest znacznie bardziej pythonowe.
eyquem,

@eyquem, używając itertools.islicezamiast [], eliminuje obiekty pośrednie. Ale ponieważ obie odpowiedzi działają na tych samych warunkach i zwracają te same, obie mają rację. I zip(i[::2], i[1::2])wygląda mi tak słodko, więc czemu nie? :)
utdemir

Działa to tylko na sekwencjach , podczas gdy odpowiedź @ kevpie jest bardziej ogólna i działa na każdej iterowalnej .
Kos

37

Użyj iteratora.

Rozumienie listy:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> [c+next(si, '') for c in si]
['abcde', 'fghijklmn', 'opqr']
  • Bardzo wydajne pod względem wykorzystania pamięci.
  • Dokładnie jedno przejście s

Wyrażenie generatora:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> pair_iter = (c+next(si, '') for c in si)
>>> pair_iter # can be used in a for loop
<generator object at 0x4ccaa8>
>>> list(pair_iter) 
['abcde', 'fghijklmn', 'opqr']
  • używać jako iteratora

Używając map, str .__ add__, iter

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> map(str.__add__, si, si)
['abcde', 'fghijklmn', 'opqr']

next (iterator [, default]) jest dostępny począwszy od Pythona 2.6


2
Zdecydowanie najlepsza odpowiedź. Zobacz mój komentarz do odpowiedzi utdemira.
eyquem,

4

żeby być pythonowym :-)

>>> x = ['a1sd','23df','aaa','ccc','rrrr', 'ssss', 'e', '']
>>> [x[i] + x[i+1] for i in range(0,len(x),2)]
['a1sd23df', 'aaaccc', 'rrrrssss', 'e']

w przypadku, gdy chcesz być zaniepokojony, jeśli długość listy jest nieparzysta, możesz spróbować:

[x[i] + x[i+1] if not len(x) %2 else 'odd index' for i in range(0,len(x),2)]

Powodzenia


2

Bez tworzenia tymczasowych list:

>>> import itertools
>>> s = 'abcdefgh'
>>> si = iter(s)
>>> [''.join(each) for each in itertools.izip(si, si)]
['ab', 'cd', 'ef', 'gh']

lub:

>>> import itertools
>>> s = 'abcdefgh'
>>> si = iter(s)
>>> map(''.join, itertools.izip(si, si))
['ab', 'cd', 'ef', 'gh']

Fajnie, ale biorąc pod uwagę, że mój kod i tak sprawia, że ​​zaczynam od oryginalnej listy, myślę, że nie wybiorę utdmr ... dziękuję jednak
John

1
>>> lst =  ['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'] 
>>> print [lst[2*i]+lst[2*i+1] for i in range(len(lst)/2)]
['abcde', 'fghijklmn', 'opqr']

1

Cóż, zrobiłbym to w ten sposób, ponieważ nie jestem dobry z Regsem ...

KOD

t = '1. eat, food\n\
7am\n\
2. brush, teeth\n\
8am\n\
3. crack, eggs\n\
1pm'.splitlines()

print [i+j for i,j in zip(t[::2],t[1::2])]

wynik:

['1. eat, food   7am', '2. brush, teeth   8am', '3. crack, eggs   1pm']  

Mam nadzieję że to pomoże :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.