Приєднання елементів списку, якщо ці елементи знаходяться між двома пробілами


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 == '']?
Олександр -

@Alexander Я думаю, що ваша пропозиція щодо другого рядка буде синтаксичною помилкою. Рядок 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, додавши список із нульовою рядком на кінцях, enumerate([''] + a + [''])потім видаляючи a[0:indx[0]]і a[indx[-1]+1:]у вашому рядку 4. Це все ще не враховує, якщо поруч з іншими є два нульові рядки хоча
Реймус Клінсман

1
Дякую @KeiNagase за прекрасні коментарі. Дивіться редагування.
наївний

2

Якщо роздільники введення насправді є порожніми рядками, то можна зробити

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

Вибачте, не побачив відповіді Непов'язаної рядки. Якщо розділити () без параметра, він зруйнує все пробіли, що трохи надійніше.
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

запустіть цикл над списком
всередині циклу, додайте елемент до тимчасової порожньої рядка і перевірте, чи є елемент порожнім рядком або останнім елементом списку, якщо це правда, то додайте тимчасову змінну до списку виводу та змініть значення цієї змінної в порожній рядок
Код:

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

Я погодився б, що у відповіді Кріса використовується більшість підходів 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]

Як зазначається в «Zen of Python : Explicit» - це краще, ніж неявне

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.