基于另一个列表拆分列表(按顺序一起处理元素)

时间:2018-01-21 22:48:48

标签: python list

我有两个列表:

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))

但是如何获得左右剩余的子列表?

4 个答案:

答案 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 ,

leftright是您想要的两个列表。我不得不说,这是一种矫枉过正。如果不存在重复项或者数组总是排序,@ 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]