4

I want to iterate through a list and sum all the elements. Except, if the number is a 5, I want to skip the number following that 5. So for example:

x=[1,2,3,4,5,6,7,5,4,3] #should results in 30.

I'm just not sure how I can access the index of a tuple, when I use enumerate. What I want to do, is use an if statement, that if the number at the previous index == 5, continue the loop.

Thanks you

Sociopath
  • 13,068
  • 19
  • 47
  • 75
Metal.days
  • 85
  • 7
  • `enumerate` gives you the index and the value. `for i, value in enumerate(x)` where `i` is the index – roganjosh Oct 03 '18 at 10:12
  • What do you mean you can’t access the index of a triple using enumerate? enumerate returns a generator of (index, value) pairs. Just iterate over that object returned by enumerate using something like `for index, value in enumerate(obj)` – blacksite Oct 03 '18 at 10:13

7 Answers7

4

The itertools documentation has a recipe for this called pairwise. You can either copy-paste the function or import it from more_itertools (which needs to be installed).

Demo:

>>> from more_itertools import pairwise
>>> 
>>> x = [1,2,3,4,5,6,7,5,4,3]
>>> x[0] + sum(m for n, m in pairwise(x) if n != 5)
30

edit:

But what if my datastructure is iterable, but does not support indexing?

In this case, the above solution needs a minor modification.

>>> from itertools import tee
>>> from more_itertools import pairwise
>>> 
>>> x = (n for n in [1,2,3,4,5,6,7,5,4,3]) # generator, no indices!
>>> it1, it2 = tee(x)
>>> next(it1, 0) + sum(m for n, m in pairwise(it2) if n != 5)
30
timgeb
  • 76,762
  • 20
  • 123
  • 145
3

Using sum with enumerate

Ex:

x=[1,2,3,4,5,6,7,5,4,3]
print(sum(v for i, v in enumerate(x) if (i == 0) or (x[i-1] != 5)))

Output:

30
Rakesh
  • 81,458
  • 17
  • 76
  • 113
3

Not a fan of bug-ridden one-liners that get upvoted.

So here's the answer with a for-loop.

x=[1,2,3,4,5,6,7,5,4,3, 5] #should results in 35. 

s = 0
for i, v in enumerate(x):
    if i != 0 and x[i-1] == 5: 
        continue 
    s += v

print(s)
Sami Farhat
  • 1,164
  • 8
  • 12
  • I would prefer if you commented on each buggy oneliner individually instead of dismissing all of them. But your solution is straight forward and deserves an upvote. – timgeb Oct 03 '18 at 10:31
2

Simple, verbose way:

SKIP_PREV = 5
x = [1,2,3,4,5,6,7,5,4,3]
prev = -1
s = 0
for num in x:
    if prev != SKIP_PREV:
        s += num
    prev = num
print(s)
# 30

Compact, maybe less clear way:

SKIP_PREV = 5
x = [1,2,3,4,5,6,7,5,4,3]
s = sum(num for i, num in enumerate(x) if i == 0 or x[i - 1] != SKIP_PREV)
print(s)
# 30
jdehesa
  • 58,456
  • 7
  • 77
  • 121
1

If you are happy to use a 3rd party library, you can use NumPy with integer indexing:

import numpy as np

x = np.array([1,2,3,4,5,6,7,5,4,3])

res = x.sum() - x[np.where(x == 5)[0]+1].sum()  # 30

See also What are the advantages of NumPy over regular Python lists?

jpp
  • 159,742
  • 34
  • 281
  • 339
0

You can pair the list with a shifted version of itself. This should work:

sum(val for (prev, val)
    in zip(itertools.chain((None,), x), x)
    if prev != 5 )
Florian Weimer
  • 32,022
  • 3
  • 48
  • 92
0

The longest code so far. Anyway, it does not need enumerate, it is a simple FSM.

x = [1,2,3,4,5,6,7,5,4,3]
skip = False
s = 0 
for v in x:
    if skip:
        skip = False
    else:
        s += v
        skip = v == 5
print(s)
VPfB
  • 14,927
  • 6
  • 41
  • 75