Unir elementos de uma lista se esses elementos estiverem entre dois espaços em branco


24

Eu tenho uma entrada como esta:

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

Eu quero unir elementos entre ''para ter uma saída como esta:

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

Tentei usar joine listar fatias como esta:

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

Isso funciona até certo ponto, mas não sei como iterar essa instrução para a lista inteira.

Respostas:


27

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

Resultado:

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

2
Explicação: Utiliza "bool" para verificar um valor "Falsey", como uma sequência vazia ou Nenhuma.
noɥʇʎԀʎzɐɹƆ

7

Isso é horrível e hacky, mas

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

pode pegar qualquer string que você possa garantir que não esteja contida na concatenação da lista e retornar uma função fazendo o que você deseja. Obviamente, você provavelmente deseja usar isso apenas uma ou duas vezes para sua situação específica; portanto, se você puder garantir que nenhum elemento da lista contenha um espaço, pode parecer mais com:

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

4

Se você não pode ou não deseja usar as ferramentas:

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

Você consegue fazer isso:

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

Resultado:

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

Editar após os comentários:

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

Resultado:

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

# get the indices.não é um comentário muito útil. Eu sugiro que você o torne útil (por exemplo filter the indices to keep only those that correspond to whitespace) ou remova-o totalmente.
Alexander - Restabelece Monica

Além disso, esse processo de duas etapas não poderia ser simplificado indices = [i for s in a if s == '']?
Alexander - Restabelece Monica

@ Alexander Eu acho que sua sugestão para a linha 2 seria um erro de sintaxe. A linha 2 pode ser removida se você simplesmente adicionar a verificação "é igual a seqüência nula" à linha três comoindx = [i for i, x in enumerate(a) if x == '']
Reimus Klinsman 11/11/19

Infelizmente, essa resposta não considera o primeiro ou o último elemento como algo que deve ser associado. como a = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+'], mas parece que você poderia melhorar sua linha 3 anexando uma lista com uma cadeia nula nas extremidades de um enumerate([''] + a + ['']), em seguida, remover o a[0:indx[0]]e a[indx[-1]+1:]em sua linha 4. Isto ainda não leva em conta se há duas cadeias nulas ao lado eachother embora
Reimus Klinsman

11
Obrigado @KeiNagase pelos bons comentários. Veja a edição.
ingênuo

2

Se os delimitadores de entrada forem realmente cadeias vazias, você poderá fazer

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

Desculpe, não vi a resposta de String não relacionada. Se você dividir () sem um parâmetro, ele recolherá todo o espaço em branco, que é um pouco mais robusto.
realgeek

1

Bastante antigo, mas ainda ú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)

Isso gera

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

1

executar um loop na lista
dentro do loop anexa o elemento a uma string vazia temporária e verifica a condição de se o elemento é uma string vazia ou o último elemento da lista, se true, acrescenta a variável temporária à lista de saída e altera o valor dessa variável para uma string vazia
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)

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


1

Concordo que a resposta Cris usa a abordagem mais python , mas será bom adaptar um pouco a resposta Cris . Em vez de usar groupby(l,key = bool)para usar groupby(l, key = lambda x: x !='')e se livrar de ambiguidade desnecessária

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 é afirmado em The Zen of Python : Explícito é melhor que implícito

PS: Só estou escrevendo a nova resposta porque não tenho reputação suficiente para escrever um comentário sobre a resposta da Cris .


1

Outra versão de trabalho, com apenas loops / testes básicos:

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.