Python—如何在列表中连接由某个值分隔的元素

Python—如何在列表中连接由某个值分隔的元素,python,list,iteration,Python,List,Iteration,假设我有一个如下所示的列表: ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8'] ['1', '+', '2', '+', '345', '-', '6', '+', '78'] 我想修改它,使所有由'C'分隔的元素连接在一起。结果应该如下所示: ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8'

假设我有一个如下所示的列表:

['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
['1', '+', '2', '+', '345', '-', '6', '+', '78']
我想修改它,使所有由
'C'
分隔的元素连接在一起。结果应该如下所示:

['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
['1', '+', '2', '+', '345', '-', '6', '+', '78']
我一直在尝试以非常简单的方式执行此操作,但问题是每当我删除一个元素时,列表的大小都会发生变化,迭代也会越界。任何指点都很感激。谢谢

过滤掉“C”,然后将连续数字分组:

from itertools import groupby

data = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
new_data = [''.join(g) if k else next(g) for k, g in groupby((el for el in data if el != 'C'), key=str.isdigit)]
# ['1', '+', '2', '+', '345', '-', '6', '+', '78']

如果下一个值不是
C
,则可以使用仅生成值的生成器函数,否则将累加:

def join_by(it, sep):
    it = iter(it)
    prev = next(it)
    for elem in it:
        if elem == sep:
            prev += next(it)
        else:
            yield prev
            prev = elem
    yield prev
演示;这不仅限于数字,也不限于特定的分隔符:

>>> orig = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
>>> list(join_by(orig, 'C'))
['1', '+', '2', '+', '345', '-', '6', '+', '78']
>>> list(join_by(['foo', '-', 'bar', 'baz'], '-'))
['foobar', 'baz']
要解决这个难题,您只需作弊并在此处使用
eval()

>>> import operator
>>> from itertools import product
>>> digits = '123456789'
>>> ops = (' - ', ' + ', '')
>>> for combo in product(ops, repeat=len(digits) - 1):
...     expr = zip(digits, combo + ('',))
...     expr = ''.join([c for digit_oper in expr for c in digit_oper])
...     result = eval(expr)
...     if result == 100:
...         print(expr)
... 
1 + 2 + 3 - 4 + 5 + 6 + 78 + 9
1 + 2 + 34 - 5 + 67 - 8 + 9
1 + 23 - 4 + 5 + 6 + 78 - 9
1 + 23 - 4 + 56 + 7 + 8 + 9
12 - 3 - 4 + 5 - 6 + 7 + 89
12 + 3 - 4 + 5 + 67 + 8 + 9
12 + 3 + 4 + 5 - 6 - 7 + 89
123 - 4 - 5 - 6 - 7 + 8 - 9
123 - 45 - 67 + 89
123 + 4 - 5 + 67 - 89
123 + 45 - 67 + 8 - 9
结果:

['1', '+', '2', '+', '345', '-', '6', '+', '78']

此代码应适用于任何给定的列表和值

old_list = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
new_list = []
for index, val in enumerate(old_list):
    if val == 'C':
        new_list[-1] += old_list[index+1]
    elif old_list[index-1] != 'C':
        new_list.append(val)

不需要理解列表,只需找到分隔符并连接其余的分隔符即可

a = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
firstIndex = a.index('C')
revertedLastIndex = a[::-1].index('C') # index in reverted list 
lastIndex = len(a) - 1 - revertedLastIndex  # -1 for 0-indexed lists
所以我们现在可以在
firstIndex
lastIndex
之间加入列表的一部分,然后连接其余的

newList = a[:firstIndex] + ["".join(a[firstIndex:lastIndex])] + a[lastIndex:]
编辑:我所说的“不需要列表理解”当然是指不需要显式迭代,
index
函数在内部执行

import ast

L=['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']

s=str(L).replace(", 'C', ", "")

out=ast.literal_eval(s)

print out
输出:

['1', '+', '2', '+', '345', '-', '6', '+', '78']

Python的奇特特性使代码的逻辑非常、非常容易理解,这非常好。当他们不这样做时,我更喜欢保持它的简单性和可验证性:

stuff = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
concat = False
newstuff = []
for a in stuff:
    if concat:
        newstuff[-1] += a
        concat = False
    elif a == "C":
        concat = True
    else:
        newstuff.append(a)

不要删除任何内容;当你浏览你的数据时,建立一个新的列表。我很好奇你是如何获得这样一个。。。有趣的数据结构。@alexis哇,我不知道这是怎么回事,虽然我在过去一个小时里没有想到……我一定是掉进了兔子洞,所有的逻辑都没有了me@TigerhawkT3问题5。假设只有数字可以连接。@Martijn确实。。。但根据OP作为评论发布的问题5,似乎只有数字在使用。。。(虽然不太确定C来自何处…)他们可能是通过在数字之间分别尝试
'+'
'-'
'C'
(用于连接)来强制解决方案。@MartijnPieters是的,这正是我正在做的。出于好奇,我想尝试一下,查看它的性能有多差,然后将其与更好的算法进行比较的愚蠢方法。
x
从何而来?
名称错误:名称“x”未定义
想要使代码更可读,却忘了将
x
更改为
val
:)
类型错误:只能将列表(而不是“str”)连接到列表
详细信息=p首先将字符串转换为列表。编辑答案