How to remove every occurrence of sub-list from list

前端 未结 13 565
走了就别回头了
走了就别回头了 2021-01-07 16:16

I have two lists:

big_list = [2, 1, 2, 3, 1, 2, 4]
sub_list = [1, 2]

I want to remove all sub_list occurrences in big_list.

result

相关标签:
13条回答
  • 2021-01-07 16:52

    (For final approach, see last code snippet)

    I'd have thought a simple string conversion would be sufficient:

    big_list = [2, 1, 2, 3, 1, 2, 4]
    sub_list = [1, 2]
    
    new_list = list(map(int, list((''.join(map(str, big_list))).replace((''.join(map(str, sub_list))), ''))))
    

    I'm essentially doing a find/replace with the string equivalents of the lists. I'm mapping them to integers afterwards so that the original types of the variables are retained. This will work for any size of the big and sub lists.

    However, it's likely that this won't work if you're calling it on arbitrary objects if they don't have a textual representation. Moreover, this method results in only the textual version of the objects being retained; this is a problem if the original data types need to be maintained.

    For this, I've composed a solution with a different approach:

    new_list = []
    i = 0
    while new_list != big_list:
        if big_list[i:i+len(sub_list)] == sub_list:
            del big_list[i:i+len(sub_list)]
        else:
            new_list.append(big_list[i])
            i += 1
    

    Essentially, I'm removing every duplicate of the sub_list when I find them and am appending to the new_list when I find an element which isn't part of a duplicate. When the new_list and big_list are equal, all of the duplicates have been found, which is when I stop. I haven't used a try-except as I don't think there should be any indexing errors.

    This is similar to @MadPhysicist's answer and is of roughly the same efficiency, but mine consumes less memory.

    This second approach will work for any type of object with any size of lists and therefore is much more flexible than the first approach. However, the first approach is quicker if your lists are just integers.

    However, I'm not done yet! I've concocted a one-liner list comprehension which has the same functionality as the second approach!

    import itertools
    new_list = [big_list[j] for j in range(len(big_list)) if j not in list(itertools.chain.from_iterable([ list(range(i, i+len(sub_list))) for i in [i for i, x in enumerate(big_list) if x == sub_list[0]] if big_list[i:i+len(sub_list)] == sub_list ]))]
    

    Initially, this seems daunting, but I assure you it's quite simple! First, i create a list of the indices where the first element of the sublist has occured. Next, for each of these indices, I check if the following elements form the sublist. If they do, the range of indices which form the duplicate of the sublist is added to another list. Afterwards, I use a function from itertools to flatten the resulting list of lists. Every element in this flattened list is an index which is in a duplicate of the sublist. Finally, I create a new_list which consists of every element of the big_list which has an index not found in the flattened list.

    I don't think that this method is in any of the other answers. I like it the most as it's quite neat once you realise how it works and is very efficient (due to the nature of list comprehensions).

    0 讨论(0)
提交回复
热议问题