Search code examples
pythonpython-3.xlistmutation

How do I mutate every third element in a list?


How do I check every third element in a list?

ie. Given the list below, I want to mutate every third item and leave the rest of the list as is.

L = [1,2,3,4,5,6,7,8,9]

Basically, if the third element in the list (in this case 3,6,9) is odd, then subtract one to make it even. If it is even, let it remain the same.

I know that if I do L[2::3] I get a new list of every third element, but I simply want to loop through every third item and check.

What would the for loop look like? I need some help.

Thanks and appreciate all help!


Solution

  • Don't overthink this. This is a case where list comprehensions, functions, and so on are all overkill. You need to iterate over a list, and modify it in-place, right? So you're not modifying the structure you're iterating over. The iteration target is actually the indices of the list.

    xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    print(xs)
    
    for idx in range(2, len(xs), 3):
        if xs[idx] % 2 == 1:
            xs[idx] -= 1
    
    print(xs)
    

    This is the equivalent of a for(i = 2; i < len(xs); i++) loop in many lower-level languages.


    Compared to the list comprehension solution proposed in another answer, the for loop is marginally faster:

    from timeit import timeit
    
    
    def in_place(xs):
        for idx in range(2, len(xs), 3):
            if xs[idx] % 2 == 1:
                xs[idx] -= 1
        return xs
    
    
    def list_comp(xs):
        xs[2::3] = [i - 1 if (i % 3 == 0 and i % 2 != 0) else i for i in xs[2::3]]
        return xs
    
    
    # This answer is an improvement, as it eliminates one modulus
    def list_comp2(xs):
        xs[2::3] = [x - 1 if x % 2 else x for x in xs[2::3]]
        return xs
    
    
    context = {"globals": globals(), "setup": "xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]"}
    print(f"For loop: {timeit('in_place(xs)', **context)}")
    print(f"List comprehension:  {timeit('list_comp(xs)', **context)}")
    print(f"List comprehension 2:  {timeit('list_comp2(xs)', **context)}")
    

    On my machine, this produces:

    For loop: 0.608657514
    List comprehension:  0.7510721879999999
    List comprehension 2:  0.641639047