Объединение элементов списка, если эти элементы находятся между двумя пробелами - PullRequest
24 голосов
/ 11 ноября 2019

У меня есть такой ввод:

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

Я хочу объединить элементы между '', чтобы получить такой вывод:

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

Я пытался использовать joinи нарезка списка следующим образом:

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

Это работает до некоторой степени, но я не знаю, как повторить эту инструкцию для всего списка.

Ответы [ 9 ]

27 голосов
/ 11 ноября 2019

Использование 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]

Вывод:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
7 голосов
/ 12 ноября 2019

Это ужасно и хакерски, но

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

может взять любую строку, которую вы можете гарантировать, что она не содержится в конкатенации списка, и вернуть функцию, выполняющую то, что вы хотите. Конечно, вы, вероятно, захотите использовать это только один или два раза для вашей конкретной ситуации, поэтому, если вы можете гарантировать, что ни один элемент списка не содержит пробела, он может выглядеть примерно так:

a = ['assembly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c++']
a = ''.join(i or ' ' for i in a).split(' ')
4 голосов
/ 11 ноября 2019

Если вы не можете или не хотите использовать 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 голосов
/ 11 ноября 2019

Вы можете сделать это:

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

Вывод:

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

Редактировать после комментариев:

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

Вывод:

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
2 голосов
/ 17 ноября 2019

Если входные разделители на самом деле являются пустыми строками, то вы можете сделать

strlist = [x or ' ' for x in a]
joined = ''.join(strlist).split()
joined
['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
1 голос
/ 06 декабря 2019

Другая рабочая версия, только с базовыми циклами / тестами:

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
1 голос
/ 28 ноября 2019

Я бы согласился, что Cris answer использует большинство подходов Python , но будет хорошо адаптировать Cris ответь немного. Вместо использования groupby(l,key = bool) для использования groupby(l, key = lambda x: x !='') и избавления от ненужной неоднозначности

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]

Как указано в Дзен Питона : Явное лучше, чем неявное

PS Я пишу только новый ответ, потому что у меня недостаточно репутации, чтобы написать комментарий к Крис ответ.

1 голос
/ 18 ноября 2019

Довольно старый, но все еще полезный:

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)

Это дает

['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']
1 голос
/ 18 ноября 2019

запустить цикл над списком
внутри цикла добавить элемент во временную пустую строку и проверить условие, является ли элемент пустой строкой или последним элементом списка, если true, затем добавить временную переменную кВыведите список и измените значение этой переменной на пустую строку
Код:

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)

Выход: ['assembly', 'python', 'java', 'ruby', 'javascript', 'c++']

...