如果列表元素在两个空格之间,则联接它们


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

这在某种程度上可行,但是我不知道如何遍历整个列表。

Answers:


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
说明:这使用“布尔”来检查“假”值,例如空字符串或无。
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行的建议将是语法错误。如果仅在第三行添加“等于空字符串”检查,则可以删除第2行,例如indx = [i for i, x in enumerate(a) if x == '']
Reimus Klinsman

不幸的是,这个答案没有考虑到第一个或最后一个元素应该被连接。就像,a = ['asse','mbly', '', 'py', 'tho', 'n', '', 'ja', 'va', '', 'rub', 'y', '', 'java', 'script', '', 'c+', '+']但是看起来您可以通过在列表的末尾附加一个带有空字符串的列表,enumerate([''] + a + [''])然后删除第4行上的a[0:indx[0]]和来改善第3 a[indx[-1]+1:]行。这仍然无法说明彼此之间是否有两个空字符串虽然
Reimus Klinsman

1
感谢@KeiNagase的出色评论。参见编辑。
天真的

2

如果输入分隔符实际上是空字符串,则可以执行

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

抱歉,没有看到无关字符串的答案。如果不带参数的split(),它将折叠所有空白,这会更健壮。
realgeek '19

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,则将临时变量追加到输出列表并更改值该变量为空字符串的
代码:

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]

正如《The Zen of Python》所述显式优于隐式

PS:我之所以写新答案,是因为我没有足够的声誉来就Cris答案发表评论。


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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.