Unir elementos de una lista si esos elementos están entre dos espacios en blanco


24

Tengo una entrada como esta:

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

Quiero unir elementos ''para tener una salida como esta:

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

Traté de usar joiny cortar en rebanadas de esta manera:

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

Esto funciona hasta cierto punto, pero no sé cómo repetir esta instrucción para toda la lista.

Respuestas:


27

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

Salida:

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

2
Explicación: Esto usa "bool" para verificar un valor de "Falsey", como una cadena vacía o Ninguno.
noɥʇʎԀʎzɐɹƆ

7

Esto es horrible y hacky, pero

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

puede tomar cualquier cadena que pueda garantizar que no esté contenida en la concatenación de la lista y devolver una función que haga lo que desee. Por supuesto, probablemente quiera usar esto solo una o dos veces para su situación específica, por lo tanto, si puede garantizar que ningún elemento de la lista contenga un espacio, podría parecerse más a:

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

4

Si no puede o no quiere usar 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

Puedes hacerlo:

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

Salida:

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

Editar después de los comentarios:

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

Salida:

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

# get the indices.No es un comentario muy útil. Te sugiero que lo hagas útil (por ejemplo filter the indices to keep only those that correspond to whitespace) o que lo elimines por completo.
Alexander - Restablece a Mónica el

Además, ¿no podría simplificarse ese proceso de 2 pasos indices = [i for s in a if s == '']?
Alexander - Restablece a Mónica el

@Alexander Creo que su sugerencia para la línea 2 sería un error de sintaxis. La línea 2 se puede eliminar si simplemente agrega la indx = [i for i, x in enumerate(a) if x == '']
marca

Desafortunadamente, esta respuesta no tiene en cuenta que el primer o el último elemento es algo que debe unirse. como a = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+'], pero parece que se podría mejorar su línea 3 añadiendo una lista con una cadena nula en los extremos de una enumerate([''] + a + [''])continuación de retirar el a[0:indx[0]]y a[indx[-1]+1:]en su línea 4. Esto todavía no dar cuenta de si hay dos cadenas nulas justo al lado de fuerza aunque
Reimus Klinsman

1
Gracias @KeiNagase por sus buenos comentarios. Ver la edición.
ingenuo

2

Si los delimitadores de entrada son realmente cadenas vacías, entonces puede hacer

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

Lo siento, no vi la respuesta de Unrelated String. Si divide () sin un parámetro, colapsará todo el espacio en blanco, que es un poco más robusto.
realgeek

1

Bastante viejo pero aún útil:

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)

Esto produce

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

1

ejecute un ciclo sobre la lista
dentro del ciclo agregue el elemento a una cadena vacía temporal y verifique la condición de si el elemento es una cadena vacía o el último elemento de la lista, si es verdadero, agregue la variable temporal a la lista de salida y cambie el valor de esa variable a una cadena vacía
Código:

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)

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


1

Estoy de acuerdo en que la respuesta Cris utiliza la mayoría de los enfoques de Python , pero será bueno adaptar un poco la respuesta Cris . En lugar de usar groupby(l,key = bool)para usar groupby(l, key = lambda x: x !='')y deshacerse de la ambigüedad innecesaria

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]

Como se afirma en The Zen of Python : explícito es mejor que implícito

PD: Solo estoy escribiendo la nueva respuesta porque no tengo suficiente reputación para escribir un comentario sobre la respuesta de Cris .


1

Otra versión de trabajo, con solo bucles / pruebas básicas:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.