0

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. I first thought of using find() but that doesn't work for lists

3 Answers3

3

You're making a critical mistake: You're modifying a list while you are iterating it. Don't do that. Sometimes the language or implementation will save you, but often times you'll end up getting strange and incorrect results.

Try instead iterating over the list by index:

for i in range(len(integer_list)):
   # You can read an item from the list:
   val = integer_list[i]

   # And you can overwrite an item in the list:
   integer_list[i] = new_val

(The exact solution is up to you to come up with.)

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • Great reply for a coursework-related question. It points out a stumbling block that even a very dedicated student might not readily discover, yet withholds "giveaway" details. – FrontRanger May 01 '21 at 20:03
-1

You can modify a list using this syntax: list[index] = whatever you want here. Indexes start at 0. Enumerate just allows you to get the index while looping, instead of doing list.index(element).

Code:

Using Enumerate:

integer_list = [1, 2, 3 , 4, 5, 6, 7]
def make_all_odd(integer_list):
    for index, number in enumerate(integer_list):
        if (number % 2) == 0:
            integer_list[index] += 1

make_all_odd(integer_list)
print(integer_list)

Without Using Enumerate (doesn't take into account duplicate value, so the even numbers all have to be different):

integer_list = [1, 2, 3 , 4, 5, 6, 7]
def make_all_odd(integer_list):
    for number in integer_list:
        index = integer_list.index(number)
        if (number % 2) == 0:
            integer_list[index] += 1

make_all_odd(integer_list)
print(integer_list)

Here I use a variable to keep track of the index instead of the .index method, and this fixes not being able to use duplicates.

integer_list = [1, 2, 3 , 4, 5, 6, 7]
index = 0
def make_all_odd(integer_list):
    for number in integer_list:
        index = integer_list.index(number)
        if (number % 2) == 0:
            integer_list[index] += 1
    index+=1

make_all_odd(integer_list)
print(integer_list)

You could also do this return a new list (if you don't want the original list to be modified):

Returning New List Using Enumerate:

integer_list = [1, 2, 3 , 4, 5, 6, 7]
def make_all_odd(integer_list):
    integer_list_copy = integer_list.copy() # remember to use .copy(), look at https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-to-prevent-it 
    for index, number in enumerate(integer_list):
        if (number % 2) == 0:
            integer_list_copy[index] = number + 1
    return integer_list_copy

make_all_odd(integer_list)
print(integer_list)

Also, don't change a list when iterating through it. It just gives everyone headaches.

KetZoomer
  • 2,701
  • 3
  • 15
  • 43
  • Sorry, I downvoted, and here's why: This is clearly a homework problem. If you present a complete solution, then the OP learns nothing, and Stack Overflow's reputation of a place that contributes to cheating increases. See how my answer instead helped to correct a problem that the OP was having without implementing the entire thing. – Jonathon Reinhart May 01 '21 at 02:31
  • 1
    The OP did try something (and got most of the way there). I also provided an explanation, instead of just dumping some code – KetZoomer May 01 '21 at 02:33
  • Also, your solution with using `.index()` to determine the index of a value is poor for two reasons: 1) It doesn't take into account duplicate values in the list and 2) It makes a O(n) problem O(n^2) for no reason. – Jonathon Reinhart May 01 '21 at 02:33
  • that's why I would use enumerate, just provided the `.index()` so the OP could understand better. edit: added disclamed to `.index()` solution – KetZoomer May 01 '21 at 02:34
-1

Keep it simple using the True/False array:

import numpy as np
L = [1, 2, 3, 4, 5, 6, 7]
L + (np.mod(L,2)==0)

which returns:

array([1, 3, 3, 5, 5, 7, 7])
Q-man
  • 2,069
  • 1
  • 17
  • 16