Python Forum

Full Version: How to convert every even number in a list to odd?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hey all, one of my revision questions was to create a func that takes a list of integer values as a list, and convert every even number into an odd number.

Expected Output:
integer_list = [1, 2, 3 , 4, 5, 6, 7]
Before: [1, 2, 3, 4, 5, 6, 7]
After: [1, 3, 3, 5, 5, 7, 7]

integer_list = [1, -2, 3 , -4, 8, 16, 21, -17]
Before: [1, -2, 3, -4, 8, 16, 21, -17]
After: [1, -3, 3, -5, 9, 17, 21, -17]

Code thus far:
def make_all_odd(integer_list):
    for number in integer_list:
        if (number % 2) == 0:
            number += 1
            integer_list.append(number)
So far, I've only figured out that I need to iterate through every element in the list and check if it is even using a for loop, but I'm not sure how to modify the original string to change the identified even numbers into odd. I know my code just adds the recently converted even to odd numbers to the end of the list, but in my case I have to replace, not add.
First of all I want to quote:

"If fact, in any programming language for most part if you mutate something while you iterating over it you living in state of sin and you deserve whatever happens to you" -- Raymond Hettinger, Python core-developer, Transforming Code into Beautiful, Idiomatic Python

Is in-place mutation of list required? Following assumes that not.

You are almost there. Just de-intent last row to same level as if and return newly constructed list (and yes, we do test our code especially then sample inputs and outputs are given):

def oddify(nums):
    odd = []
    for num in nums:
        if num % 2 == 0:
            num += 1
        odd.append(num)
    return odd

assert oddify([1, 2, 3, 4, 5, 6, 7]) == [1, 3, 3, 5, 5, 7, 7]
assert oddify([1, -2, 3, -4, 8, 16, 21, -17]) == [1, -3, 3, -5, 9, 17, 21, -17]
We have encountered assertion error. Why? Because -2 + 1 = -1 but -3 is expected. We can mitigate this problem using conditional expression to determine whether we need add 1 or -1:

def oddify(nums):
    odd = []
    for num in nums:
        if num % 2 == 0:
            num += 1 if 0 < num else -1
        odd.append(num)
    return odd

assert oddify([1, 2, 3, 4, 5, 6, 7]) == [1, 3, 3, 5, 5, 7, 7]
assert oddify([1, -2, 3, -4, 8, 16, 21, -17]) == [1, -3, 3, -5, 9, 17, 21, -17]
No assertion error anymore. But... if there is value of 0 in input list then we will (probably) have wrong answer. Why probably? 0 is considered even number but it's unclear whether 0 should be converted to -1 or 1 (or should it kept unchanged). As this is homework you should figure it out yourself and adjust conditional expression accordingly if needed :-)
Hi,

In order to cope with the negative numbers,
an even shorter alternative could be to divide num by abs(num).
That gives 1 or -1 as needed.

Paul
@DPaul, good point.

def oddify_int(iterable):
    """
    Generator to oddify integers from iterable.
    
    If the even value is positive, 1 is added
    If the even value is negative, 1 is subtracted
    0 is not affected.
    """
    for value in iterable:
        
        # optional type checking to prevent the use
        # of floats or other types like Decimal, Fraction etc...
        if not isinstance(value, int):
            raise ValueError(f"'{value}' is not an int.")
                
        if value % 2 == 0 and value != 0:
            sign = abs(value) // value
            value += sign
            # (x + -1) == (x - 1)
        yield value
def oddify(arr):
    for n, i in enumerate(arr):
        if i%2 == 0:
            if i >= 0: arr[n] += 1
            else: arr[n] -= 1
    return arr