21

Rather simple question. Say I have a list like:

a = [3, 4, 54, 8, 96, 2]

Can I use slicing to leave out an element around the middle of the list to produce something like this?

a[some_slicing]
[3, 4, 8, 96, 2]

were the element 54 was left out. I would've guessed this would do the trick:

a[:2:]

but the result is not what I expected:

[3, 4]
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Gabriel
  • 40,504
  • 73
  • 230
  • 404
  • I don't understand what's the difference between the slicing you are talking about and poping out an element from a list?...I honestly don't see any difference?...what is your point here of calling it slicing?..rather than deleting an element? – Iron Fist Jun 10 '15 at 13:31
  • Because I don't want to remove an element from the list, I want to unpack its elements leaving out one in the middle: E.g: `a1, a2, a3, a4, a5 = a[:2:]` (which of course does not work) – Gabriel Jun 10 '15 at 13:32
  • People if you are going to downvote, please leave a comment so I know why you thought the question had no merit? Otherwise there's nothing I can do to fix it and there's nothing I can learn from it to avoid in the future. – Gabriel Jun 10 '15 at 13:33
  • 1
    I believe the question was, whether you can pop with a single slice, to which the answer is no. See also, this [post](http://stackoverflow.com/a/509295/89391). – miku Jun 10 '15 at 13:33
  • Iron Fist, the big difference is that the former returns a list while the latter returns None. for those who like clean, elegant, solutions, being able to pass the result of an operation onto the next can be important. – jcomeau_ictx Jan 27 '17 at 22:23

6 Answers6

29

You cannot emulate pop with a single slice, since a slice only gives you a single start and end index.

You can, however, use two slices:

>>> a = [3, 4, 54, 8, 96, 2]
>>> a[:2] + a[3:]
[3, 4, 8, 96, 2]

You could wrap this into a function:

>>> def cutout(seq, idx):
        """
        Remove element at `idx` from `seq`.
        TODO: error checks.
        """
        return seq[:idx] + seq[idx + 1:]

>>> cutout([3, 4, 54, 8, 96, 2], 2)
[3, 4, 8, 96, 2]

However, pop will be faster. The list pop function is defined in listobject.c.

Community
  • 1
  • 1
miku
  • 181,842
  • 47
  • 306
  • 310
  • Thanks miku, I was wondering if there might be a way to do that using a single slice of the list but I guess the answer is simply "no". – Gabriel Jun 10 '15 at 13:31
8

To remove an item in-place call:

your_list.pop(index)

It will return the removed item and change your_list.

Klaus D.
  • 13,874
  • 5
  • 41
  • 48
  • However on large lists this could be quite slow as everything after `index` needs to be shifted forward. – kylieCatt Jun 10 '15 at 13:42
  • 3
    On large lists it is significantly faster than the slice copy aproach. `timeit.timeit('your_list.pop(1)', setup='your_list=range(10**6)', number=1000)` → `1.010901927947998`; `timeit.timeit('your_list = your_list[:4] + your_list[5:]', setup='your_list=range(10**6)', number=1000)` → `23.652629137039185` – Klaus D. Jun 10 '15 at 13:55
  • @KlausD., thanks for the timeit. Linked your answer in my answer. – miku Jun 10 '15 at 20:17
6

To work on any size list:

a.pop((len(a)-1)//2)
Alecg_O
  • 892
  • 1
  • 9
  • 19
4

Slice the two parts separately and add those lists

a[:2] + a[3:]
Vikas Ojha
  • 6,742
  • 6
  • 22
  • 35
0

I would go with a list comprehension:

>>> a = [3, 4, 54, 8, 96, 2]
>>> a_ = [list(j for idx, j in enumerate(a) if idx != 2)]
>>> [3, 4, 8, 96, 2]
bigBlind
  • 41
  • 1
  • 1
  • 4
-1

It is the easiest answer:

>>>a = [3, 4, 54, 8, 96, 2]

>>>a.remove(54)

[3, 4, 8, 96, 2]

Community
  • 1
  • 1
  • This is not a good solution as if the number is unknown but only the location/inex is wanted to be filtered out. – Jason Liu Apr 02 '20 at 22:55