5

Is there syntax to get the elements of a list not within a given slice? Given the slice [1:4] it's easy to get those elements:

>>> l = [1,2,3,4,5]
>>> l[1:4]
[2, 3, 4]

If I want the rest of the list I can do:

>>> l[:1] + l[4:]
[1, 5]

Is there an even more succinct way to do this? I realize that I may be being too needy because this is already very concise.

EDIT: I do not think that this is a duplicate of Invert slice in python because I do not wish to modify my original list.

Community
  • 1
  • 1
aberger
  • 2,299
  • 4
  • 17
  • 29
  • 3
    This might not be what you want, so I'm putting it in a comment instead of answer, but if you want to modify the original list, you can assign into the slice. e.g. `l[1:4] = []` – recursive Feb 08 '17 at 18:39
  • You can also use numpy arrays. – arshajii Feb 08 '17 at 18:40
  • You can `del l[1:4]` if you don't mind manipulating the list, but it doesn't return it back. – ryugie Feb 08 '17 at 18:42
  • 3
    Possible duplicate of [Invert slice in python](http://stackoverflow.com/questions/13115435/invert-slice-in-python) – Wondercricket Feb 08 '17 at 18:51

5 Answers5

3

If you want to modify the list in-place, you can delete the slice:

>>> l = [1, 2, 3, 4, 5]
>>> del l[1:4]
>>> l
[1, 5]

Otherwise your originally suggestion would be the most succinct way. There isn't a way to get the opposite of a list slice using a single slice statement.

Tyler
  • 91
  • 2
  • 5
0

Clearly the best solution to create a class to encapsulate some magical behavior that occurs when you use 'c' as the step value. Clearly.

class SuperList(list):
    def __getitem__(self, val):
        if type(val) is slice and val.step == 'c':
            copy = self[:]
            copy[val.start:val.stop] = []
            return copy

        return super(SuperList, self).__getitem__(val)


l = SuperList([1,2,3,4,5])
print l[1:4:'c'] # [1, 5]
Jared Goguen
  • 8,772
  • 2
  • 18
  • 36
0
[x for i, x in enumerate(l) if i not in range(1, 4)]

Which is less concise. So the answer to your question is no, you can't do it more concisely.

Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
0

I was looking for some solution for this problem that would allow for proper handling of the step parameter as well. None of the proposed solution was really viable, so I ended up writing my own:

def complement_slice(items, slice_):
    to_exclude = set(range(len(items))[slice_])
    step = slice_.step if slice_.step else 1
    result = [
        item for i, item in enumerate(items) if i not in to_exclude]
    if step > 0:
        return result
    else:
        return result[::-1]

ll = [x + 1 for x in range(5)]
# [1, 2, 3, 4, 5]
sl = slice(1, 4)

ll[sl]
# [2, 3, 4]

complement_slice(ll, sl)
# [1, 5]

To the best of my knowledge, it does handle all the corner cases as well, including steps, both positive and negative, as well as repeating values.

I wanted to write it as a generator, but I got annoyed by checking all corner cases for positive/negative/None values for all parameters. In principle, that is possible, of course.

norok2
  • 25,683
  • 4
  • 73
  • 99
-2

You can use list comprehension with loop

l = [i for i in l if i not in l[1:4]]
SHIVAM JINDAL
  • 2,844
  • 1
  • 17
  • 34