0

Let's say I have this list:

lst = [1, 2, 3, 4]

and I want to check if a certain value answers to a condition, and if yes, modify that value. What is the best way to do it? Like a mix of clarity and efficiency. I came up with these 3 options:

# option 1
for i, item in enumerate(lst):
    if item == 2:
        lst[i] = 7

# option 2
counter = 0
for i in lst:
    if i == 2:
        lst[counter] = 7
    counter += 1

# option 3
for i in range(len(lst)):
    if lst[i] == 2:
        lst[i] = 7
Vijay Anand Pandian
  • 1,027
  • 11
  • 23
Yaniv K.
  • 237
  • 4
  • 12
  • from personal experience, i find no. 3 to be most readable and easy to do :-) – Cut7er Sep 15 '18 at 13:02
  • 15
    Option 4 is a list-comp: `lst[:] = [7 if v == 2 else v for v in lst]`... – Jon Clements Sep 15 '18 at 13:03
  • 2
    Here it turns out it does not matter, but it is good practice not to update and object over which you are iterating, making the `range` approach the preferred one. – Olivier Melançon Sep 15 '18 at 13:05
  • @JonClements What is going on here? I don't like these one line codes – Yaniv K. Sep 15 '18 at 13:06
  • Possible duplicate of https://stackoverflow.com/questions/2582138/finding-and-replacing-elements-in-a-list-python – Sruthi Sep 15 '18 at 13:07
  • 4
    @YanivK. it's called a "list comprehension" - you'll find them a fair bit in Python - so it's definitely not a bad idea if you familiarise yourself with them. http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/ is a relatively nice overview which at the top also links to the rather concise Python docs at https://docs.python.org/3/tutorial/datastructures.html#tut-listcomps – Jon Clements Sep 15 '18 at 13:08
  • 2
    @YanivK. To add a bit to what Jon said: List comprehensions are basically an efficient and clean way to build new lists. While I understand the fact that you're wary of one-line solutions - and rightfully so, people often do overuse them - your case is an example where a one-line solution is not only okay but the best option. – Christian Dean Sep 15 '18 at 13:12
  • @JonClements I agree, in the meantime while learning list comprehensions I am going to second using the 3rd option – vash_the_stampede Sep 15 '18 at 13:16
  • @vash_the_stampede really...? It's more idiomatic when wanting the index *and value* of a list to use `enumerate`... Naming the value appropriately can make the `if` check have a certain amount of context to it and it avoids the double lookup by index... – Jon Clements Sep 15 '18 at 13:20
  • @JonClements If you look here, code reveiw,and books the frequency option 3 is higher and would be beneficial to be more fluid with that to help keep the learning process going, but I respect your experience I'm only a month into this and just reading the points you made I agree `enumerate` is a better option and am gong to start incorporating its usage, but again I'm on here and books all day and you see `(range(len(lst))` in almost everything, so just to be on the same page while learning would help alleviate getting hung up – vash_the_stampede Sep 15 '18 at 13:27
  • 1
    @vash_the_stampede if you only want the index - aren't going to bother with the value because you're using the index to access something related - then sure - there's no harm in using `range(len(lst))` - however, don't forget that things can be iterated over that aren't necessarily sequences (eg: they don't have a length (so `len(obj)` will fail) - so you'd have to enumerate or for-loop and keep your own counter)... Unless you have a real reason not to use `enumerate` or where you're going to be accessing the value of the current iterationn - I'd suggest you get into the habit of using that :) – Jon Clements Sep 15 '18 at 13:39
  • @JonClements already on it, cheers! – vash_the_stampede Sep 15 '18 at 14:09

1 Answers1

0

I would suggest to use a mixture of list comprehension and function definition:

lst = [1, 2, 3, 4]

def replace(x,y=2,z=7):
    """Replace value if condition holds. 

    Keyword arguments:
    x -- value to check for replacement
    y -- x will be replaced if it has the value of y
    z -- x will be replaced by z if x is equal to y
    """
    if(x==y):
        x=z
    return x

lst = [replace(x,2,7) for x in lst]