Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing list elements that satisfy some condition with items from another list in Python

Tags:

Suppose I have those two lists

a=[0,1,6,4,2,8] 
b=[10,20,30,40]

I want to replace elements in list a that are between 0 and 4 with items from list b.

In other words, my output should be

[10,20,6,30,40,8]

Note that essentially, we strip list a of elements satisfying a certain condition and simply replacing it with an item from list b onto this. (The ordering in b is maintained)

EDIT

I actually know that exactly N number of items in list a satisfy the condition imposed. Then I need to "replace" these in-place with another list b of size N.

like image 836
Vinayak Suresh Avatar asked Jul 30 '18 18:07

Vinayak Suresh


1 Answers

Considering your edit, I would suggest using this simple and readable for loop.

a=[0,1,6,4,2,8] 
b=[10,20,30,40]
upper_bound = 4
lower_bound = 0
exclusions = range(lower_bound,upper_bound+1)

for index,item in enumerate(a):
  if item in exclusions:
    a[index] = b.pop(0)

print(a)
>>>>[10, 20, 6, 30, 40, 8]

Basically, here I'm iterating over a copy of the a list and once I find an item in the range of my specified bounds I pop the first element of b feeding it back to a.

Important Note

It is important to understand that I used an exclusions list, which I agree can be ommitted in your particular case, in order to allow someone to add string objects to the list and still have the same kind of behavior. Obviously, you could use something like,

if item > lower_bound and item < upper_bound

Which would be more efficient for your specific case since you're not creating an unecessary list.


To answer @Julian concerns, let's say your lists becomes string objects,

a=['a','b','c','d','e','f'] 
b=['test','test','test','test']

And instead of replace 0 to 4, you want to replace a c to f. With my solution it would go like this,

exclusions = ['c','d','e','f']

for index,item in enumerate(a):
    if item in exclusions:
    a[index] = b.pop(0)

print(a)
>>>>['a', 'b', 'test', 'test', 'test', 'test']

With @Julian answer,

b_iter = iter(b)
print([item if item < 0 or item > 4 else b_iter.next() for item in a])
>>>> TypeError: '<' not supported between instances of 'str' and 'int'

Now as he said, > and < operators can be used to compare two strings, so I mean he could go and change his comparisons to string type,

b_iter = iter(b)
print([item if item < '0' or item > '4' else b_iter.next() for item in a])
>>>>['a', 'b', 'c', 'd', 'e', 'f']

that would still be completely wrong because comparing objects other than int or float with < and > makes no sense in the context of OP's question.

Also, it becomes even more apparent when you use other types,

a=[{1,2},{2,3},{3,4},{4,5},{5,6},{6,7}] 
b=[{'test'},{'test'},{'test'},{'test'}]

exclusions = [{3,4},{4,5},{5,6},{6,7}]

for index,item in enumerate(a):
  if item in exclusions:
    a[index] = b.pop(0)

print(a)
>>>> [{1, 2}, {2, 3}, {'test'}, {'test'}, {'test'}, {'test'}]

b_iter = iter(b)
print([item if item < 0 or item > 4 else b_iter.next() for item in a])
>>>> TypeError: '<' not supported between instances of 'set' and 'int'

Now, I wouldn't know how he would go and fix that following his logic.

So as I said, in his comment section, make sure to be aware of what his answer implies.

like image 118
scharette Avatar answered Sep 28 '22 19:09

scharette