Python 基于另一个列表拆分列表(元素按顺序一起处理)
我有两份清单:Python 基于另一个列表拆分列表(元素按顺序一起处理),python,list,Python,List,我有两份清单: a = [1,2,3,4,5,6,7,8,9,10] b = [4,5,6] 我试图根据列表b作为边界条件来拆分列表a,这样我可以得到两个子列表作为a的左右部分,如下所示: # left sublist [1,2,3] # right sublist [7,8,9,10] 从a中删除b非常容易 filter(lambda x: x not in b, a) 或 但如何获取左侧和右侧剩余的子列表?如果第一个数组已排序,则可以使用此命令获取左侧列表: a[:a.index
a = [1,2,3,4,5,6,7,8,9,10]
b = [4,5,6]
我试图根据列表b
作为边界条件来拆分列表a
,这样我可以得到两个子列表作为a
的左右部分,如下所示:
# left sublist
[1,2,3]
# right sublist
[7,8,9,10]
从a中删除b非常容易
filter(lambda x: x not in b, a)
或
但如何获取左侧和右侧剩余的子列表?如果第一个数组已排序,则可以使用此命令获取左侧列表:
a[:a.index(b[0])]
a[a.index(b[-1]) + 1:]
对于右侧列表:
a[:a.index(b[0])]
a[a.index(b[-1]) + 1:]
如果数组未排序或包含重复项,一种方法是使用一点字符串魔法:将两个列表转换为字符串(在数字之间使用分隔符,如
,
),根据第二次拆分拆分第一个字符串,然后将每个字符串转换回整数列表。守则的内容如下:
str_a = ",".join(map(lambda x: str(x), a)) # str_a = '1,2,3,4,5,6,7,8,9,10'
str_b = ",".join(map(lambda x: str(x), b)) # str_b = '4,5,6'
str_left, str_right = str_a.split(str_b) # str_left = '1,2,3,'
# str_right = ',7,8,9,10'
left = list(map(lambda x: int(x), str_left[:-1].split(','))) # [:-1] is there to get rid of the trailing ,
right = list(map(lambda x: int(x), str_right[1:].split(','))) # [1:] is there to get rid of leading ,
left
和right
是您想要的两个列表。但我不得不说,这是一种过度的杀伤力。如果不存在重复项或数组总是被排序,@NaWeeD的答案很好。通用解决方案(不假设数组被排序或具有唯一元素,如果分隔符出现多次,则有效):
病理学的例子:
array_split([1,2,3,4,5,4,5,6,7,8,9,10], [4,5,6]) == [[1, 2, 3, 4, 5], [7, 8, 9, 10]]
这也可以简单地转换为生成器。实现这一点的一般方法是创建一个函数,首先提取由于基本列表中的子列表而创建的段的索引。然后根据这些片段对基本列表进行切片 以下是示例生成器,用于
生成因子列表创建的段
:
def get_segment_index(base_list, sub_list):
cursor, len_sub, len_base = 0, len(sub_list), len(base_list)
for i in range(len_base-len_sub+1):
if base_list[i:i+len_sub] == sub_list: # check for the match of sub-list
yield cursor, i
cursor = i+len_sub
else: # to yield the last segment
if cursor != len_base:
yield cursor, len_base
>>> a = [1, 4, 5, 6, 2, 3, 9, 7, 8, 10, 4, 5, 6, 9, 2]
# ^ ^ ^ ^ ^ ^
>>> b = [4,5,6]
>>> [a[x:y] for x, y in get_segment_index(a, b)]
[[1], [2, 3, 9, 7, 8, 10], [9, 2]]
>>> a = ['I', 'am', 'sample', 'example', 'to', 'split', 'based', 'on', 'sample', 'example', 'sublist']
# ^ ^ ^ ^
>>> b = ['sample', 'example']
>>> [a[x:y] for x, y in get_segment_index(a, b)]
[['I', 'am'], ['to', 'split', 'based', 'on'], ['sublist']]
现在在列表理解中使用上述函数,您可以通过列表切片获得所需的片段。例如:
带有编号列表的样本运行:
def get_segment_index(base_list, sub_list):
cursor, len_sub, len_base = 0, len(sub_list), len(base_list)
for i in range(len_base-len_sub+1):
if base_list[i:i+len_sub] == sub_list: # check for the match of sub-list
yield cursor, i
cursor = i+len_sub
else: # to yield the last segment
if cursor != len_base:
yield cursor, len_base
>>> a = [1, 4, 5, 6, 2, 3, 9, 7, 8, 10, 4, 5, 6, 9, 2]
# ^ ^ ^ ^ ^ ^
>>> b = [4,5,6]
>>> [a[x:y] for x, y in get_segment_index(a, b)]
[[1], [2, 3, 9, 7, 8, 10], [9, 2]]
>>> a = ['I', 'am', 'sample', 'example', 'to', 'split', 'based', 'on', 'sample', 'example', 'sublist']
# ^ ^ ^ ^
>>> b = ['sample', 'example']
>>> [a[x:y] for x, y in get_segment_index(a, b)]
[['I', 'am'], ['to', 'split', 'based', 'on'], ['sublist']]
使用字符串列表运行示例:
def get_segment_index(base_list, sub_list):
cursor, len_sub, len_base = 0, len(sub_list), len(base_list)
for i in range(len_base-len_sub+1):
if base_list[i:i+len_sub] == sub_list: # check for the match of sub-list
yield cursor, i
cursor = i+len_sub
else: # to yield the last segment
if cursor != len_base:
yield cursor, len_base
>>> a = [1, 4, 5, 6, 2, 3, 9, 7, 8, 10, 4, 5, 6, 9, 2]
# ^ ^ ^ ^ ^ ^
>>> b = [4,5,6]
>>> [a[x:y] for x, y in get_segment_index(a, b)]
[[1], [2, 3, 9, 7, 8, 10], [9, 2]]
>>> a = ['I', 'am', 'sample', 'example', 'to', 'split', 'based', 'on', 'sample', 'example', 'sublist']
# ^ ^ ^ ^
>>> b = ['sample', 'example']
>>> [a[x:y] for x, y in get_segment_index(a, b)]
[['I', 'am'], ['to', 'split', 'based', 'on'], ['sublist']]
由于子列表只出现一次,并且需要左值和右值,因此可以简单地执行以下操作:
>>> a = [1,2,3,4,5,6,7,8,9,10]
>>> b = [4,5,6]
>>> left, right = [a[x:y] for x, y in get_segment_index(a, b)]
# Left sublist
>>> left
[1, 2, 3]
# Right sublist
>>> right
[7, 8, 9, 10]
那么第一个数组被排序了?第二个数组中元素的顺序在第一个数组中是相同的?对两个问题都是。如果您只想将第一个数组按第二个数组的内容拆分,则不需要对数组进行排序。您应该编辑您的问题并包含附加信息,数组已排序且不包含重复的元素。因为b的最后一个元素在索引(b[-1])上,这不包括有[1,2,3,3,4,5]并尝试在[3,4,5]上拆分的情况。如果列表有重复项,则此操作将失败。列表将不包含任何重复项。谢谢你提出这个问题,如果
b
在a
的末尾,你应该检查一下。这只是检查可能的异常的一个简单的解决方案。欢迎光临@cbk200@cbk200@NaWeeD只有当a
或b
由连续数字组成时,此选项才有效,否则中间元素可能会发生变化,例如a:[1,2,3,5,7,8],b:[3,4,7]会错误地拆分为[1,2],[8]。请参阅我的答案以获得一般解决方案。