Python 根据可变字符串和可变块长度将列表拆分为子列表

Python 根据可变字符串和可变块长度将列表拆分为子列表,python,string,split,sublist,Python,String,Split,Sublist,我有一个字符串列表: ['splitter001','stringA','stringB','splitter_1234','stringC'] 我希望我的最终结果是: [ ['splitter001','stringA','stringB'] , ['splitter_1234','stringC'] ] 拆分器和分隔器不是完全相同的字符串 我已尝试。如果元素索引>0,则查找“拆分器”,然后删除索引[:第二个拆分器]并将第一个组附加到新列表中,但这无法正常工作 我在所有字符串上迭代for循

我有一个字符串列表:

['splitter001','stringA','stringB','splitter_1234','stringC']
我希望我的最终结果是:

[ ['splitter001','stringA','stringB'] , ['splitter_1234','stringC'] ]
拆分器和分隔器不是完全相同的字符串

我已尝试。如果元素索引>0,则查找“拆分器”,然后删除索引[:第二个拆分器]并将第一个组附加到新列表中,但这无法正常工作

我在所有字符串上迭代for循环,但对第二组无效,因此我可以得到:

[ ['splitter001','stringA','stringB'] ] as my new list, but the second group is missing.
我已经阅读了很多关于这个主题的答案,最接近的解决方案是使用:

[list(x[1]) for x in itertools.groupby(myList, lambda x: x=='#') if not x[0]] 

但是我不懂这个语法。。。我读过groupby和intertools,但我不确定这对我的情况是否有帮助。

这里有一种方法,使用
for
循环,正如您提到的,它处理第二组的情况:

# define list of strings for input
strings = ['splitter001','stringA','stringB','splitter_1234','stringC']
split_strings = []  # this is going to hold the final output
current_list = []  # this is a temporary list

# loop over strings in the input
for s in strings:
    if 'splitter' in s:
        # if current_list is not empty
        if current_list:
            split_strings.append(current_list)  # append to output
            current_list = []  # reset current_list
    current_list.append(s)

# outside of the loop, append the leftover strings (if any)
if current_list:
    split_strings.append(current_list)
这里的关键是,在循环之外的末尾再追加一次,以捕获最后一个组

输出:

[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
编辑:添加代码解释

我们创建一个临时变量
current\u list
来保存我们将附加到最终输出
split\u strings
的每个列表

循环输入中的字符串。对于每个字符串
s
,检查它是否包含
“拆分器”
。如果它是空的并且当前列表不是空的,这意味着我们已经点击了下一个分隔符。将
current_list
附加到输出并清除它,以便我们可以开始收集下一组字符串的项

检查后,将当前字符串附加到
当前\u列表
。这是因为我们在找到分隔符后清除了它(将其设置为
[]


在列表的末尾,我们将剩余的内容附加到输出中(如果有的话)。

这里有一种方法可以通过
groupby
实现这一点。我们告诉
groupby
查找以“splitter”开头的字符串。这将创建两种类型的组:以“splitter”开头的字符串和所有其他字符串。例如

from itertools import groupby

data = ['splitter001','stringA','stringB','splitter_1234','stringC']

for k, g in groupby(data, key=lambda s: s.startswith('splitter')):
    print(k, list(g))
输出

True ['splitter001']
False ['stringA', 'stringB']
True ['splitter_1234']
False ['stringC']
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
['splitter001', 'stringA', 'stringB']
['splitter_1234', 'stringC']
因此,我们可以将这些组分为两个列表,然后将它们压缩在一起,形成最终列表

from itertools import groupby

data = ['splitter001','stringA','stringB','splitter_1234','stringC']

head = []
tail = []
for k, g in groupby(data, key=lambda s: s.startswith('splitter')):
    if k:
        head.append(list(g))
    else:
        tail.append(list(g))

out = [u+v for u, v in zip(head, tail)]
print(out)
输出

True ['splitter001']
False ['stringA', 'stringB']
True ['splitter_1234']
False ['stringC']
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
['splitter001', 'stringA', 'stringB']
['splitter_1234', 'stringC']
这里有一种更简洁的方法来做同样的事情,使用列表列表来存储头列表和尾列表:

from itertools import groupby

data = ['splitter001','stringA','stringB','splitter_1234','stringC']
results = [[], []]
for k, g in groupby(data, key=lambda s: s.startswith('splitter')):
    results[k].append(list(g))

out = [v+u for u, v in zip(*results)]
print(out)
输出

True ['splitter001']
False ['stringA', 'stringB']
True ['splitter_1234']
False ['stringC']
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
['splitter001', 'stringA', 'stringB']
['splitter_1234', 'stringC']

如果要在单独的行上打印每个子列表,最简单的方法是使用
for
循环,而不是创建
out
列表

for u, v in zip(*results):
    print(v + u)
输出

True ['splitter001']
False ['stringA', 'stringB']
True ['splitter_1234']
False ['stringC']
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
[['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]
['splitter001', 'stringA', 'stringB']
['splitter_1234', 'stringC']
另一种方法是将子列表转换为字符串,然后用换行符将它们连接在一起以创建一个大字符串

print('\n'.join([str(v + u) for u, v in zip(*results)]))

最后一个变体将这两种组存储到一个迭代器对象中。我想你会同意以前的版本更容易阅读。:)


获取
startswith('splitter')
元素的索引,然后在这些索引处切片列表

sl = ['splitter001','stringA','stringB','splitter_1234','stringC']

si = [i for i, e in enumerate(sl) if e.startswith('splitter')]
[sl[i:j] for i, j in zip(si, si[1:] + [len(sl)])]

Out[66]: [['splitter001', 'stringA', 'stringB'], ['splitter_1234', 'stringC']]

您可以尝试以下方法:

当出现
拆分器
时,首先获取
从到
索引号,然后根据这些索引点击列表:

sl = ['splitter001','stringA','stringB','splitter_1234','stringC']

si = [index for index, value in enumerate(sl) if value.startswith('splitter')]
for i in range(0,len(si),1):

    slice=si[i:i+2]
    if len(slice)==2:
        print(sl[slice[0]:slice[1]])
    else:
        print(sl[slice[0]:])
输出:

['splitter001', 'stringA', 'stringB']
['splitter_1234', 'stringC']

不确定您是否可以通过使用
groupby
来实现这一点。像
[list(group)for u,group in groupby(l,key=lambda x:x.startswith('splitter'))]
这样的解决方案会将splitter*元素保留在单独的子列表中。但有趣的问题!我不明白这里的逻辑。首先,为找到的每个字符串拆分器创建一个占位符空列表,然后将字符串放在那里,但我看不到其他字符串是如何进入当前列表的?您好,从第一次阅读来看,这似乎是可行的,但是您能解释几件事吗:1-列表(g)中的列表指的是什么?只是g是一个列表的事实?2-输出的内容=?这是一个存储结果的变量吗?为什么不直接使用结果本身呢?@YafimSimanovsky 1
groupby
生成的组是迭代器,因此我们需要将这些迭代器转换为适当的列表。如果将
list(g)
调用替换为
g
,请参见我的第一个示例中打印的内容。2当然,我可以重新循环
结果
,而不是使用名称
out
。我想使用一个单独的名称可以清楚地表明它们是两个不同的列表,具有不同的结构。@YafimSimanovsky您可能会发现这篇文章很有趣:谢谢。我在groupby(data,key=lambda s:s.startswith('splitter'):results[k].append(list(g))解决方案中尝试了它,但有两件事:1-我得到的输出是[['splitter001','stringA','stringB','splitter_1234',['stringC']],我需要以不同的方式追加列表吗?我完全按照你写的那样试过了。2-当我尝试使用:def print_dataset(dataset):for each in dataset:print each打印整个结果列表时,它不会用行分隔元素breaks@YafimSimanovsky对不起!我在那个版本中做了一个复制粘贴错误:它有
u+v
而不是
v+u
。这是因为我在同一个脚本中有所有3个版本。2我将添加更多的代码来演示如何在一瞬间将子列表打印在单独的行上。