如果列表项与先前的项不包含某个前缀,我将尝试将它们合并,并在此列表项之间添加\n
。
prefix = '!'
cmds = ['!test','hello','world','!echo','!embed','oh god']
output = ['!test\nhello\nworld','!echo','!embed\noh god']
我尝试过类似的
for i in list(range(0,len(cmds))):
if not cmds[i+1].startswith(prefix):
cmds[i] += cmds.pop(i+1)
但总是会收到list index out of range
错误。
我很抱歉,如果措辞不好,或者似乎是一个明显的解决方法,我对python / programming还是陌生的。
编辑:
我设法使其与
一起使用prefix = '!'
cmds = ['!test','hello','world','!echo','!embed','oh god']
print(list(range(0,len(cmds))))
for i in reversed(range(len(cmds))):
if not cmds[i].startswith(prefix):
cmds[i-1] += '\n'+cmds.pop(i)
print(cmds)
,但是您的答案似乎更加整洁和有效。非常感谢大家
答案 0 :(得分:8)
我建议创建一个新列表,如您的问题说明中所示:
prefix = '!'
cmds = ['!test','hello','world','!echo','!embed','oh god']
output = []
for cmd in cmds:
if cmd.startswith(prefix) or not output:
output.append(cmd)
else:
output[-1] += "\n" + cmd # change the string in the last element of output
结果是:
>>> output
['!test\nhello\nworld', '!echo', '!embed\noh god']
答案 1 :(得分:3)
这是一个使用itertools.groupby
和itertools.accumulate
的单线解决方案:
from itertools import accumulate, groupby
from operator import itemgetter
x = ['!test','hello','world','!echo','!embed','oh god']
cumsum = accumulate(map(lambda s: s.startswith('!'), x))
result = ['\n'.join(map(itemgetter(0), g)) for _, g in groupby(zip(x, cumsum), itemgetter(1))]
这看起来像两条衬里,因为我想使它清晰易读,但这并不总是必要的:
result = ['\n'.join(map(itemgetter(0), g)) for _, g in groupby(zip(x, accumulate(map(lambda s: s.startswith('!'), x))), itemgetter(1))]
cumsum
提供到目前为止找到的以!
开头的元素数。这为groupby
提供了一个不错的关键。它通过将str.startswith
返回的布尔值累加为整数来工作。
最终结果使用cumsum
作为键,但是将x
的分组元素与换行符连接。
这是一个IDEOne Link。
答案 2 :(得分:1)
您可以使用列表理解“也”来做到这一点。
In [1]: cmds = ['!test','hello','world','!echo','!embed','oh god']
In [2]: prefix = '!'
In [3]: inds = [i for i, x in enumerate(cmds) if prefix in x]
In [4]: inds.append(len(cmds))
In [5]: lens = list(zip(inds, inds[1:]))
# [(0, 3), (3, 4), (4, 6)]
In [6]: ["\n".join(cmds[a:b]) for a, b in lens]
Out[6]: ['!test\nhello\nworld', '!echo', '!embed\noh god']
答案 3 :(得分:1)
更长的解决方案,但可以使用itertools.groupby轻松推广到其他情况:
from itertools import groupby
class StartGroupOnPrefix:
def __init__(self, prefix):
self.output = False
self.prefix = prefix
def __call__(self, item):
if item.startswith(self.prefix):
self.output = not self.output
return self.output
prefix = '!'
cmds = ['!test','hello','world','!echo','!embed','oh god']
condition = StartGroupOnPrefix(prefix)
out = ['\n'.join(group) for f, group in groupby(cmds, condition)]
print(out)
# ['!test\nhello\nworld','!echo','!embed\noh god']
因为我们有一个迭代器,所以我们不必一次创建整个输出列表,我们可以即时生成每个输出:
for grouped_item in ('\n'.join(group) for f, group in groupby(cmds, condition)):
print('-----------\n', grouped_item)
# -----------
# !test
# hello
# world
# -----------
# !echo
# -----------
# !embed
# oh god
一些解释:groupby(iterable)
每次从iterable
获得不同的项目时都会开始一个新组。每当groupby(iterable, key)
函数的返回值更改时,key
就会开始一个新组。每当项目以前缀开头时,我们的condition
函数就会在True
和False
之间交替输出。