1

I would like to delete multiple items in a list by their index:

dS = [0, 0.02, 0, 0.04, 0.07, 0]
dN = [1, 0.02, 0.3, 0.7, 0.9]
pos = [i for i, e in enumerate(dS) if e ==0]

And now I would like to delete (in both lists) all the items on the positions of 0's in the first list.

KaDeK970123
  • 31
  • 1
  • 6

4 Answers4

5

Assuming you have any old_list with a list of index pos that you want to get rid of:

new_list = [old_list[i] for i, e in enumerate(old_list) if i not in pos]

This will work for both the list in your question by getting rid of the element at index specified by pos, just substitute old_list with list name you currently have:

dS = [0, 0.02, 0, 0.04, 0.07, 0]
dN = [1, 0.02, 0.3, 0.7, 0.9]
pos = [i for i, e in enumerate(dS) if e ==0]
dS = [dS[i] for i, e in enumerate(dS) if i not in pos]
dN = [dN[i] for i, e in enumerate(dN) if i not in pos]
>>> dS, dN
([0.02, 0.04, 0.07], [0.02, 0.7, 0.9])

This work fine for list which lengths are different, as shown in your case above.

Rocky Li
  • 5,641
  • 2
  • 17
  • 33
  • 1
    This feels the most Pythonic to me. It's readable, and each list of `dS` and `dN` are independent of each other. – Kirk Strauser Nov 30 '18 at 20:54
  • 1
    `pos` should probably be a `set` for faster lookup – Jean-François Fabre Nov 30 '18 at 21:18
  • 2
    You could also use directly the "e" variable and get rid of the lookup, as in `dS = [e for i, e in enumerate(dS) if i not in pos]` – Lohmar ASHAR Nov 30 '18 at 21:48
  • @RockyLi, comparing your solution with the one I suggested (this one: https://stackoverflow.com/a/53564806/10642035), yours, since you're creating 2 new lists for the task, is way slower (2 times as slow). Using timeit to compare both, here the measurement, using 100000 runs: Mine - 0.15612420099205337 Yours - 0.3033675350015983 – Luan Naufal Dec 01 '18 at 15:21
1

I would like to delete (in both lists) all the items on the positions of 0's in the first list.

Okay first process the second list by picking only the items of the same index than the non-zero items of the first list:

dN = [dN[i] for i, e in enumerate(dS) if e]

then do the same for dS (note: a variant would be to use filter in that case):

dS = list(filter(None,dS))
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 1
    This assumes both lists are of the same length. If `dN` is larger, this solution will truncate its elements in the final result. – slider Nov 30 '18 at 20:35
0

You have a choice of making new copies of each list with certain elements omitted, or modifying both lists in place.

dS = [0, 0.02, 0, 0.04, 0.07, 0]
dN = [1, 0.02, 0.3, 0.7, 0.9]

# make copies of both lists while omitting indices
# that corresponds to zeros in dS
dS, dN = map(list, zip(*[(s, n) for s, n in zip(dS, dN) if s != 0]))

# alternatively, modify lists inplace
dS = [0, 0.02, 0, 0.04, 0.07, 0]
dN = [1, 0.02, 0.3, 0.7, 0.9]

# process lists in reverse
for i in range(1, len(dS)):
    try:
        if dS[-i] == 0:
            del dS[-i], dN[-i]
    except IndexError:
        break
hilberts_drinking_problem
  • 11,322
  • 3
  • 22
  • 51
0

Since your lists have different lengths, you only need to run through your list pos and delete from both lists, such as: (important to run in reverse order in the pos, to ensure you won't try to delete an element index that no longer exists)

for idx in pos[::-1]:
        del dS[idx]
        if idx < len(dN):
            del dN[idx]
Luan Naufal
  • 1,346
  • 9
  • 15