Unire elementi di un elenco se tali elementi si trovano tra due spazi bianchi


24

Ho un input come questo:

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

Voglio unire gli elementi tra loro ''per avere un output come questo:

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

Ho provato a usare joined elencare lo slicing in questo modo:

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

Questo funziona in una certa misura, ma non so come ripetere queste istruzioni per l'intero elenco.

Risposte:


27

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

Produzione:

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

2
Spiegazione: Questo usa "bool" per controllare un valore "Falsey", come una stringa vuota o None.
noɥʇʎԀʎzɐɹƆ

7

Questo è terribile e confuso, ma

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

può prendere qualsiasi stringa che puoi garantire non sia contenuta nella concatenazione dell'elenco e restituire una funzione che fa quello che vuoi. Naturalmente, probabilmente vuoi usarlo solo una o due volte per la tua situazione specifica, quindi, se puoi garantire che nessun elemento dell'elenco contiene uno spazio, potrebbe assomigliare di più a:

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

4

Se non puoi o non vuoi usare itertools:

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 = ""

3

Puoi farlo:

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

Produzione:

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

Modifica dopo i commenti:

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

Produzione:

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

# get the indices.non è un commento molto utile. Suggerirei di renderlo utile (ad esempio filter the indices to keep only those that correspond to whitespace) o di rimuoverlo del tutto.
Alexander - Ripristina Monica l'

Inoltre, non è possibile semplificare quel processo in 2 passaggi indices = [i for s in a if s == '']?
Alexander - Ripristina Monica l'

@Alexander Penso che il tuo suggerimento per la riga 2 sarebbe un errore di sintassi. La riga 2 può essere rimossa se aggiungi semplicemente il controllo "è uguale alla stringa nulla" alla riga tre come:indx = [i for i, x in enumerate(a) if x == '']
Reimus Klinsman,

Sfortunatamente, questa risposta non tiene conto del fatto che il primo o l'ultimo elemento debba essere unito. come a = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+']ma sembra che potresti migliorare la tua linea 3 aggiungendo un elenco con una stringa nulla alle estremità di un enumerate([''] + a + [''])quindi rimuovendo la a[0:indx[0]]e a[indx[-1]+1:]sulla tua linea 4. Ciò non tiene conto se ci sono due stringhe null proprio una accanto all'altra però
Reimus Klinsman l'

1
Grazie @KeiNagase per i bei commenti. Vedi la modifica.
ingenuo

2

Se i delimitatori di input sono in realtà stringhe vuote, è possibile farlo

strlist = [x or ' ' for x in a]
joined = ''.join(strlist).split()
joined
['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

Siamo spiacenti, non ho visto la risposta di Unrelated String. Se dividi () senza un parametro, comprimerà tutto lo spazio bianco, il che è un po 'più robusto.
realgeek,

1

Abbastanza vecchio ma comunque utile:

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)

Questo cede

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

1

eseguire un ciclo sull'elenco
all'interno del ciclo aggiungere l'elemento a una stringa vuota temporanea e verificare la condizione se l'elemento è una stringa vuota o l'ultimo elemento dell'elenco, se vero quindi aggiungere la variabile temporanea all'elenco di output e modificare il valore di quella variabile in una stringa vuota
Codice:

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)

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


1

Concordo sul fatto che la risposta di Cris utilizza la maggior parte dell'approccio Python , ma sarà bene adattare un po 'la risposta di Cris . Invece di usare groupby(l,key = bool)per usare groupby(l, key = lambda x: x !='')e sbarazzarsi di inutili ambiguità

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]

Come è affermato in The Zen of Python : Explicit è meglio di implicito

PS Sto solo scrivendo la nuova risposta perché non ho abbastanza reputazione per scrivere un commento sulla risposta di Cris .


1

Un'altra versione funzionante, con solo loop / test di base:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.