Verbinden von Elementpaaren einer Liste


82

Ich weiß, dass eine Liste verbunden werden kann, um eine lange Zeichenfolge zu erstellen, wie in:

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

Offensichtlich würde dies Folgendes ausgeben:

'abcd'

Ich versuche jedoch, einfach die erste und die zweite Zeichenfolge in der Liste zu verbinden, dann die dritte und vierte Zeichenfolge und so weiter. Kurz gesagt, erzielen Sie aus dem obigen Beispiel stattdessen eine Ausgabe von:

['ab', 'cd']

Gibt es eine einfache Möglichkeit, dies zu tun? Ich sollte wahrscheinlich auch erwähnen, dass die Länge der Zeichenfolgen in der Liste unvorhersehbar ist, ebenso wie die Anzahl der Zeichenfolgen in der Liste, obwohl die Anzahl der Zeichenfolgen immer gerade sein wird. Die ursprüngliche Liste könnte also genauso gut sein:

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

"Ich sollte wahrscheinlich auch erwähnen, dass die Länge der Zeichenfolgen in der Liste unvorhersehbar sein wird" - Ist die Länge also wichtig? Dh möchten Sie nur jedes Paar von Listenelementen verbinden, oder möchten Sie sich tatsächlich den Inhalt ansehen und beitreten, solange das resultierende Element unter einer bestimmten Längenbeschränkung bleibt?
stupsen

Schließen Sie sich einfach jedem Paar an, ich dachte nur, dass es ein Problem sein könnte, die Anzahl der Paare nicht zu kennen
John

Antworten:


74

Sie können die Slice-Notation mit folgenden Schritten verwenden:

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

Die gleiche Logik gilt auch für Listen. Die Länge der Zeichenfolge spielt keine Rolle, da Sie einfach zwei Zeichenfolgen addieren.


1
Es besteht kein Zweifel, dass Kevpies Antwort weitaus besser ist. In diesem x[:::2]Fall wird ein Objekt x[1::2]erstellt, ein anderes Objekt erstellt. Diese Kreationen basieren wahrscheinlich auf der Berechnung von Indizes unter der Haube. Ein Aufruf einer Funktion mit diesen beiden als Argumente übergebenen Objekten ist erforderlich, bevor die aufeinanderfolgenden Elementpaare abgerufen werden können das muss verkettet werden. Während in kevpies Antwort nur ein Iterator erstellt wird, springt die Iteration von Element zu Element der unberührten Liste, ohne sich um die Indizes kümmern zu müssen, und das ist weitaus pythonischer.
Eyquem

@eyquem entfernt itertools.isliceanstelle von [] die Zwischenobjekte. Da beide Antworten unter denselben Bedingungen funktionieren und dieselben zurückgeben, haben beide Recht. Und zip(i[::2], i[1::2])sieht für mich so süß aus, warum also nicht? :)
utdemir

Dies funktioniert nur bei Sequenzen , während die Antwort von @ kevpie allgemeiner ist und bei allen iterierbaren Sequenzen funktioniert .
Kos

37

Verwenden Sie einen Iterator.

Listenverständnis:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> [c+next(si, '') for c in si]
['abcde', 'fghijklmn', 'opqr']
  • Sehr effizient für die Speichernutzung.
  • Genau eine Durchquerung von s

Generatorausdruck:

>>> 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']
  • als Iterator verwenden

Verwenden Sie map, str .__ add__, iter

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

next (Iterator [, Standard]) ist ab Python 2.6 verfügbar


2
Mit Abstand die beste Antwort. Siehe meinen Kommentar zur Antwort von utdemir.
Eyquem

4

nur um pythonisch zu sein :-)

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

Falls Sie alarmiert werden möchten, wenn die Listenlänge ungerade ist, können Sie Folgendes versuchen:

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

Viel Glück


2

Ohne temporäre Listen zu erstellen:

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

oder:

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

Schön, aber wenn man bedenkt, dass mein Code mich trotzdem mit der ursprünglichen Liste beginnen lässt, denke ich, dass ich mich für utdmr's entscheide ... danke aber
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

Nun, ich würde es so machen, da ich mit Regs nicht gut bin.

CODE

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

Ausgabe:

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

Hoffe das hilft :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.