Verknüpfen von Elementen einer Liste, wenn sich diese Elemente zwischen zwei Leerzeichen befinden

24

Ich habe eine Eingabe wie diese:

['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

Ich möchte Elemente zusammenfügen '', um eine Ausgabe wie diese zu erhalten:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

Ich habe versucht, joinSlicing wie folgt zu verwenden und aufzulisten:

a=['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
a[2:5] = [''.join(a[ 2: 5])]
a=['assembly', '', 'python', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

Dies funktioniert bis zu einem gewissen Grad, aber ich weiß nicht, wie ich diese Anweisung für die gesamte Liste wiederholen soll.

Mewtire
quelle

Antworten:

27

Verwenden von itertools.groupby:

from itertools import groupby

l = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
new_l = [''.join(g) for k, g in groupby(l, key = bool) if k]

Ausgabe:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
Chris
quelle
2
Erläuterung: Hierbei wird "bool" verwendet, um nach einem "Falsey" -Wert zu suchen, z. B. nach einer leeren Zeichenfolge oder "Keine".
noɥʇʎԀʎzɐɹƆ
7

Das ist schrecklich und hackig, aber

lambda b:lambda l:''.join(i or b for i in l).split(b)

Sie können jede Zeichenfolge verwenden, von der Sie garantieren können, dass sie nicht in der Verkettung der Liste enthalten ist, und eine Funktion zurückgeben, die das tut, was Sie möchten. Natürlich möchten Sie dies wahrscheinlich nur ein- oder zweimal für Ihre spezielle Situation verwenden. Wenn Sie also garantieren können, dass kein Element der Liste ein Leerzeichen enthält, sieht es möglicherweise eher so aus:

a = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
a = ''.join(i or ' ' for i in a).split(' ')
Nicht verwandte Zeichenfolge
quelle
4

Wenn Sie itertools nicht verwenden können oder wollen:

l = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
l_new = []
combined = ""
for idx, s in enumerate(l):
    if s != "":
        combined += s
        if idx == len(l)-1:
            l_new.append(combined)

    else:
        l_new.append(combined)
        combined = ""
Asad
quelle
3

Du kannst das:

a = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
indx = ['' == k for k in a]
indx = [i for i, x in enumerate(indx) if x] # get the indices.
a_merged = a[0:indx[0]] + [''.join(a[indx[i]:indx[i+1]]) for i in range(len(indx)) if i < len(indx)-1] + a[indx[-1]+1:] # merge the list

Ausgabe:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

Nach Kommentaren bearbeiten:

a = ['assembly', '','',  'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
indx = [i for i, x in enumerate(a) if x == ''] # get the indices where '' occurs in the original list. 
a_merged = a[0:indx[0]] + [''.join(a[indx[i]:indx[i+1]]) for i in range(len(indx)) if i < len(indx)-1 and indx[i+1] -indx[i] > 1] + a[indx[-1]+1:]
a_merged

Ausgabe:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
naiv
quelle
# get the indices.ist kein sehr nützlicher Kommentar. Ich würde vorschlagen, dass Sie es entweder nützlich machen (z. B. filter the indices to keep only those that correspond to whitespace) oder es vollständig entfernen.
Alexander - Reinstate Monica
Könnte dieser zweistufige Prozess nicht einfach vereinfacht werden indices = [i for s in a if s == '']?
Alexander - Reinstate Monica
@ Alexander Ich denke, Ihr Vorschlag für Zeile 2 wäre ein Syntaxfehler. Zeile 2 kann entfernt werden, wenn Sie einfach die Prüfung "ist gleich null" in Zeile drei wieindx = [i for i, x in enumerate(a) if x == '']
Reimus Klinsman
Leider berücksichtigt diese Antwort nicht, dass das erste oder letzte Element verbunden werden sollte. wie, a = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+']aber es sieht so aus, als könnten Sie Ihre Zeile 3 verbessern, indem Sie eine Liste mit einer Nullzeichenfolge an den Enden von a anhängen und enumerate([''] + a + [''])dann das a[0:indx[0]]und a[indx[-1]+1:]in Ihrer Zeile 4 entfernen. Dies berücksichtigt immer noch nicht, ob zwei Nullzeichenfolgen direkt nebeneinander liegen obwohl
Reimus Klinsman
1
Danke @KeiNagase für die schönen Kommentare. Siehe die Bearbeitung.
naiv
2

Wenn die Eingabetrennzeichen tatsächlich leere Zeichenfolgen sind, können Sie dies tun

strlist = [x or ' ' for x in a]
joined = ''.join(strlist).split()
joined
['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
Realgeek
quelle
Entschuldigung, ich habe die Antwort von Unrelated String nicht gesehen. Wenn Sie split () ohne Parameter teilen, wird das gesamte Leerzeichen reduziert, was etwas robuster ist.
Realgeek
1

Ziemlich alt, aber immer noch nützlich:

from itertools import groupby

lst = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

new_lst = [''.join(values)
           for key, values in groupby(lst, key = lambda x: x == '')
           if not key]
print(new_lst)

Dies ergibt

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
Jan.
quelle
1

Führen Sie eine Schleife über die Liste
innerhalb der Schleife aus. Hängen Sie das Element an eine temporäre leere Zeichenfolge an und prüfen Sie, ob das Element eine leere Zeichenfolge oder das letzte Element der Liste ist. Wenn dies der Fall ist, hängen Sie die temporäre Variable an die Ausgabeliste an und ändern Sie den Wert dieser Variablen in eine leere Zeichenfolge
Code:

x=['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
temp=''
output=[]
for y in x:
    temp=temp+y
    if y=='' or y==x[-1]:
        output.append(temp)
        temp=''

print(output)

Ausgabe: ['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

Eswar
quelle
1

Ich würde zustimmen, dass die Cris- Antwort den meisten Python-Ansatz verwendet , aber es wird gut sein, die Cris- Antwort ein wenig anzupassen . Anstatt unnötige Mehrdeutigkeitengroupby(l,key = bool) zu verwenden groupby(l, key = lambda x: x !='')und zu beseitigen

from itertools import groupby

separator = ''
l = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
new_l = [''.join(g) for k, g in groupby(l, key = lambda x: x !=separator) if k]

Wie es im Zen of Python heißt : Explizit ist besser als implizit

PS Ich schreibe nur die neue Antwort, weil ich nicht genug Ruf habe, um einen Kommentar zur Cris- Antwort zu schreiben .

N.Nonkovic
quelle
1

Eine andere funktionierende Version mit nur grundlegenden Schleifen / Tests:

txt = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']

out = []
temp = ''

for s in txt:
   if s == '':
      if temp != '':
         out.append(temp) 
         temp = ''
      out.append('')
   else:
      temp = temp + s

if temp != '':
   out.append(temp)

out
B. Geh
quelle