Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基于另一个列表拆分列表(元素按顺序一起处理)_Python_List - Fatal编程技术网

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]。请参阅我的答案以获得一般解决方案。