user3654650
user3654650

Reputation: 6103

How to perform operation on elements of list which depend on previous elements?

Using map can do operations of current element in list:

l = [1,2,3,4,5,6];


print(list(map(lambda x: x*2, l)))  
# gives [2, 4, 6, 8, 10, 12]

In above, multiply by 2 is done for all elements in l. But how to mulitiply by 2 an element in l, only if previous value in l is odd? Can use map for this?

For example to get:

[1,4,3,8,5,12] % only 2, 4 and 6 from l are multiplyied by 2, because before them there are odd numbers 1,3,5. 

Upvotes: 1

Views: 1211

Answers (5)

Peter Gibson
Peter Gibson

Reputation: 19554

I realise that it was probably just a trivial example, but thought it worth mentioning that in your example case the condition "if the previous value is odd" is the same as "if the current value is even" (at least for your sample input). In which case I would just use

print([x if x&1 else x*2 for x in l])

For the more general case and assuming the condition may be more complex than just "previous item is odd", I would take a few lines to express the solution clearly. Python's generators are a good fit:

>>> def double_if_prev_odd(l):
...     prev_odd = False # initial condition for 1st element
...     for x in l:
...             yield x**2 if prev_odd else x
...             prev_odd = x&1
...
>>> list(double_if_prev_odd(l))
[1, 4, 3, 16, 5, 36]

Upvotes: 0

Brendan F
Brendan F

Reputation: 629

You can use something callable to track your previous value. Depending on how abstract you want this:

prev = [0]
def callback(x):
    val = ((prev[0] % 2) + 1) * x
    prev[0] = x
    return val

print list(map(callback, l))

Upvotes: 0

Matthew Trevor
Matthew Trevor

Reputation: 14962

You can zip the list along with a sliced copy of the list to pair all of the items:

>>> l = [1, 2, 3, 4, 5, 6]
>>> zip(l, l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

Upvotes: 2

Amber
Amber

Reputation: 526683

You can use map if you do it on an enumerated version:

print(list(map(lambda index,x: x*2 if index > 1 and l[index-1] & 1 else x, enumerate(l))))

However, as you might have noticed, that's really not very readable. It's better to just use a list comprehension or a for loop:

print([x*2 if index > 1 and l[index-1] & 1 else x
       for index, x in enumerate(l)])

Upvotes: 3

Greg Hewgill
Greg Hewgill

Reputation: 993213

You can use zip in combination with map:

print(l[:1] + list(map(lambda x: x[1]*2 if x[0] & 1 else x[1], zip(l, l[1:]))))

Note that I had to explicitly prepend the first element of the list because it has no previous element to test.

Upvotes: 2

Related Questions