Объединение элементов списка, если эти элементы находятся между двумя пробелами


24

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

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

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

Ответы:


27

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

2
Объяснение: При этом используется «bool» для проверки значения «Falsey», такого как пустая строка или None.
noɥʇʎԀʎzɐɹƆ

7

Это ужасно и смешно, но

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

Если вы не можете или не хотите использовать 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

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

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

# get the indices.не очень полезный комментарий. Я бы посоветовал вам либо сделать это полезным (например filter the indices to keep only those that correspond to whitespace), либо полностью удалить его.
Александр - Восстановить Монику

Кроме того, нельзя ли просто упростить этот двухэтапный процесс indices = [i for s in a if s == '']?
Александр - Восстановить Монику

@ Александр Я думаю, что ваше предложение для строки 2 будет синтаксической ошибкой. Строка 2 может быть удалена, если вы просто добавите флажок «равно пустой строке» к строке три, напримерindx = [i for i, x in enumerate(a) if x == '']
Реймус Клинсман

К сожалению, этот ответ не учитывает, что первый или последний элемент является чем-то, что должно быть объединено. вроде бы, a = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+']но похоже, что вы могли бы улучшить свою строку 3, добавив список с нулевой строкой на концах a, enumerate([''] + a + [''])затем удалив строку a[0:indx[0]]и a[indx[-1]+1:]в своей строке 4. Это по-прежнему не учитывает наличие двух нулевых строк рядом с eachother хотя
Реймус Клинсман

1
Спасибо @KeiNagase за хорошие комментарии. Смотрите редактирование.
Наивный

2

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

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

Извините, не видел ответ Unrelated String. Если вы разделяете () без параметра, он разрушит все пробелы, которые немного более устойчивы.
Realgeek

1

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

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

выполните цикл над списком
внутри цикла, добавьте элемент во временную пустую строку и проверьте условие, является ли элемент пустой строкой или последним элементом списка, если значение true, то добавьте временную переменную в выходной список и измените значение этой переменной в пустую строку
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)

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


1

Я согласен с тем, что в ответе Cris используется большинство подходов 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]

Как сказано в Дзен Python : явное лучше, чем неявное

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


1

Еще одна рабочая версия, только с базовыми циклами / тестами:

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.