我有两个列表:
a = [1,2,3,4,5,6,7,8,9,10]
b = [4,5,6]
我正在尝试根据作为边界条件的列表a
拆分列表b
,以便我可以将两个子列表作为 left 和对 a
的一部分:
# left sublist
[1,2,3]
# right sublist
[7,8,9,10]
从 a 中删除 b 非常简单,
filter(lambda x: x not in b, a)
或
list(set(a) - set(b))
但是如何获得左右剩余的子列表?
答案 0 :(得分:1)
如果第一个数组已排序,您可以使用它来获取左侧列表:
a[:a.index(b[0])]
和右手名单:
a[a.index(b[-1]) + 1:]
答案 1 :(得分:1)
通用解决方案(不排除正在排序的数组或具有唯一元素的假设,如果分隔符多次出现,则有效):
def array_split(arr, separator):
result = [] # list of the sublists
current_part = [] # current sublist we're assembling
possible_separator = [] # store possible separator here (e.g. if the separator is 4,5,6 and we've got 4,5 so far)
for i in arr:
if i == separator[len(possible_separator)]: # matches next piece of separator?
if len(possible_separator) == len(separator) - 1: # separator complete
result.append(current_part)
current_part = []
possible_separator.clear()
else: # add to possible separator
possible_separator.append(i)
else:
current_part.extend(possible_separator) # wasn't the full separator, add to sublist and clear
possible_separator.clear()
current_part.append(i)
result.append(current_part)
return result
一个病态的例子:
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]]
这也可以简单地转换为生成器。
答案 2 :(得分:0)
如果数组未被排序或包含重复项,一种方法是使用一点字符串魔法:将两个列表转换为字符串(在数字之间使用,
之类的分隔符),拆分关于第二个拆分的第一个字符串,然后将每个字符串转换回整数列表。代码就是这样:
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的答案可以正常工作。
答案 3 :(得分:0)
实现此目的的一般方法是创建一个函数,首先提取由于子列表中的子列表而创建的段的索引。然后根据这些段切割您的基本列表。
以下是样本生成器yield
由于子列表而创建的细分:
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
现在在列表理解中使用上述功能,您可以在 list slicing 的帮助下获得所需的片段。例如:
使用数字列表运行示例:
>>> 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]