Removing a sublist from a list
Asked Answered
V

2

0

I have a list e.g. l1 = [1,2,3,4] and another list: l2 = [1,2,3,4,5,6,7,1,2,3,4]. I would like to check if l1 is a subset in l2 and if it is, then I want to delete these elements from l2 such that l2 would become [5,6,7,1,2,3,4], where indexes 0-3 have been removed.

Is there a pythonic way of doing this?

I tried this:

l1 = [1,2,3,4]
l2 = [1,2,3,4,5,6,7,1,2,3,4]
l3 = []
for i in l2:
    if i in l1:
        l3.append(i)
-> prints [5,6,7]

However I would like the output to be [5,6,7,1,2,3,4].

Verdure answered 19/3, 2017 at 0:51 Comment(1)
[i for i in l1+l2 if (i not in l1) or (i not in l2)] I think this is all you needDeprecate
L
3

Well, here is a brute-force way. There are probably more efficient ways. If you expect to encounter a matching sublist early, the performance shouldn't be terrible.

>>> l1 = [1,2,3,4]
>>> l2 = [1,2,3,4,5,6,7,1,2,3,4]
>>> for i in range(0, len(l2), len(l1)):
...     if l2[i:len(l1)] == l1:
...         del l2[i:len(l1)]
...         break
...
>>> l1
[1, 2, 3, 4]
>>> l2
[5, 6, 7, 1, 2, 3, 4]
>>>

Or if you don't want to modify l2, you could do the following:

>>> l1 = [1,2,3,4]
>>> l2 = [1,2,3,4,5,6,7,1,2,3,4]
>>> for i in range(0, len(l2), len(l1)):
...     if l2[i:len(l1)] == l1:
...         break
...
>>> l2[:i] + l2[i+len(l1):]
[5, 6, 7, 1, 2, 3, 4]
>>>
Lenlena answered 19/3, 2017 at 0:56 Comment(0)
J
0

I'm not proud of this, and it's not pythonic, but I thought it might be a bit of fun to write. I've annotated the code to make it a little more obvious what's happening.

>>> import re
>>> from ast import literal_eval

>>> l1 = [1,2,3,4]
>>> l2 = [1,2,3,4,5,6,7,1,2,3,4]
>>> literal_eval(         # convert the string into a python collection
...    re.sub(            # use a regex as a replacement
...       str(l1)[1:-1],  # string of the list, without surrounding brackets
...       '',             # replace with empty
...       str(l2)[1:-1],  # string for replacement, again without brackets
...       count=1         # only replace the first match
...    ).strip(',')       # replace any preceeding or trailing commas
...     .strip()          # replace any preceeding or trailing whitespace
... )
(5, 6, 7, 1, 2, 3, 4)

The output here is a tuple, but you could wrap it in list() if that's what you really want. Again, I'm not proud of this, but it works at least for this simple case. Juanpa's solution is much more preferable to this.

Jesselton answered 19/3, 2017 at 1:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.