Multiplying only odd indexes in a for loop - python

Multiplying only odd indexes with for loop
Why its not working?
myList = [1, 2, 3, 4, 5]
index = 0
for num in myList:
if index % 2 != 0:
num *= 2
index += 1
print(myList) # here the output still the same list
I want the output to be [1, 4, 3, 8, 5]

Edit: I see that you have edited your question, where you fixed the first issue of checking if the items in the list are odd or not. You are however still iterating over the list using for num in myList, which under the hood creates an Iterator which moves over your list. This means that whatever you do with num, you are only modifying num and not myList[index]. In order to modify the list directly, you will need to reference myList[index]. I strongly recommend you look into using enumerate, see my original answer for how to apply it to your use-case.
Your problem is that you are checking if the value inside myList is even or odd instead of its index.
Also, modifying num within the loop does not modify the value in your original list (this can easily be noticed since in the "modified" list the odd values are not multiplied).
Using the range(len()) idiom to loop over your list would yield the following code:
myList = [1, 2, 3, 4, 5]
for idx in range(len(myList)):
if idx % 2 != 0:
myList[idx] *= 2
print(myList)
You could further shorten the loop/assignment by using enumerate and list comprehension:
myList = [1, 2, 3, 4, 5]
myList = [num * 2 if idx % 2 != 0 else num for idx, num in enumerate(myList)]
print(myList)

Your way isn't working because you are not assigning 'num' back into the list.
newList = [v*2 if idx % 2 != 0 else v for idx, v in enumerate(myList)]

There are two issues in the code -
You need to check if the index is odd or even, and not the element.
Modifying num won't modify the corresponding element in the list as it does not reference the element in the list.
myList = [1, 2, 3, 4, 5]
for idx in range(len(myList)):
if idx % 2 != 0:
myList[idx]*=2

Related

How can I increase the value in list

I've wrote the following code
numbers = [1, 2, 3, 4]
lst = [None] * 3
for i in range(0, 3):
lst[i] = numbers[:]
So if I want to increase the value in first lst by 1 and increase the value in second lst my 2 and so on.
Can I solve this question by for loop?
A possible approach:
numbers=[1, 2, 3, 4]
lst = [None] *3
for i in range(0,3):
lst[i] = [x+i+1 for x in numbers]
Here during each iteration we create new lists by adding i+1 to each value in the list, numbers.
For reference this approach is called list comprehension.
You can do this with list comprehension.
numbers = [i+1+a for i,a in enumerate(numbers)]
Where i will be the index number(I added the +1 since it begins with 0), so for index 1 it will add 1, for index 2 it will add 2 and so on..
And a is the value held at the current index.
which will give an output of:
[2, 4, 6, 8]

How do I mutate every third element in a list? [duplicate]

This question already has answers here:
Edit the value of every Nth item in a list
(7 answers)
how to replace every n-th value of an array in python most efficiently?
(3 answers)
Closed 3 years ago.
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!
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
You can just do a list comprehension using slicing to modify selected values based on condition:
L[2::3] = [x - 1 if x % 2 else x for x in L[2::3]]
Example:
L = [1,2,3,4,5,6,7,8,9]
L[2::3] = [x - 1 if x % 2 else x for x in L[2::3]]
# [1, 2, 2, 4, 5, 6, 7, 8, 8]
You can assign to slices and in this example then use a list comprehension to do the mutation.
L = [1,2,3,4,5,6,7,8,9]
L[2::3] = [ x if x % 2 == 0 else x-1 for x in L[2::3] ]
print(L)
Though despite the syntactic beauty, a simple for loop reads better for your future self and colleagues =D
Define the function you want to apply to the elements an iterate using a list comprehension
def do(number):
if number%2 == 1:
return number -1
else:
return number
[do(y) if i%3 == 0 else y for i,y in enumerate(L)]
a different solution not using enumerate explicitly could be:
for i in range(len(L)):
if i%3 == 0:
L[i] = do(L[i])
You also might want to check this about inlace operations
List comprehension is the best option:
L = [1,2,3,4,5,6,7,8,9]
L[2::3] = [i-1 if (i%3==0 and i%2!= 0) else i for i in L[2::3]
print(L)
Output:
[1, 2, 2, 4, 5, 6, 7, 8, 8]
Explanation:
Basically you look at each third element in L and see if it is divisible by 3 (remainder is 0) AND not even (mod2 is not 0) and if so subtract 1 from it, otherwise keep it as is. Replace result in the original list.

What am I doing wrong? It shows me that the list index is out of range

I have a given list and I want to add all elements of that list with an odd index to the new list. Here is my code :
def odd_indices(lst):
new_lst = [ lst[i] for i in lst if (i + 2) % 2 != 0 ]
return new_lst
What am I doing wrong?
You might want to take the index instead of the value itself. The list lst contains values and not indices. enumerate helps generating indices. Do like below.
def odd_indices(lst):
new_lst = [ v for i, v in enumerate(lst) if i% 2 != 0 ]
return new_lst
print(odd_indices([1, 2, 4, 5]))
You could slice the list as follows:
lst[1::2]
The general syntax is:
list[start:end:step]
in the list comprehension[lst[i] for i in lst if (i + 2) % 2 != 0] you iterate over items in the list and try to obtain elements from the original list with the respective index i if i+2 is odd.
as mentioned in other replies you can use enumerate to access index and element.
or you can simply use slicing
>>> foo = [1, 2, 3, 4, 5]
>>> foo[1::2]
[2, 4]
Use enumerate to work on index
>>> lst = [0,1,2,3,4,5,6,7,8,9,10]
>>> [value for index, value in enumerate(lst) if index%2 != 0]
[1, 3, 5, 7, 9] # output odd index values
What is the mistake you have done?
Iterating through list.
In each iteration you will get the element of that list.
you are using that element as the index of the list.
EX:
lst = [1,2,3,4,5,6,7,8,9,10]
In above lst, the last element is 10.
lst[10] ---> which does not exists. # Throws out of index range error

List index out of range even when loops don't iterate on the lists

I'm a beginner at python coding and I've been trying to do this exercise to remove all adjacent characters from a list of integers to a single element using the following block of code:
#nums is a list of integers with repeating adjacent characters. For eg. [1,2,2,2,3,3]
length = len(nums)
for i in range(length):
while nums[i] == nums[i+1]:
del(nums[i+1])
length-=1
I keep getting the list index out of range error on the while loop, but since neither of the loops depends on the indices of nums directly, then how am I violating the bounds of the list?
I have previously checked with other answers to the same problem which all have solutions that relate to list comprehension which I don't want to apply to my code. Also, I'm aware of other approaches to removing adjacent elements but I would like to know what was wrong with my bit of code here for learning purposes. Thanks in advance.
I've added a check for confirming length. Is this what you want? It simply executes the loop if items are available.
nums = [1, 2, 2, 2, 3, 3]
length = len(nums)
for i in range(length):
while i < length-1 and nums[i] == nums[i + 1] :
del (nums[i + 1])
length -= 1
print(nums)
There are 2 errors here.
You are iterating over a range which cannot be indexed; in this case, the nums[len(nums)] does not exist. Remember Python indexing begins at 0.
You are modifying your list as you iterate. Don't do this, as the length of your list will change and your iteration will not work as intended.
Here is some code that works:
nums = [1,2,2,2,3,3]
length = len(nums)
items = []
for i in range(length-1):
if nums[i] == nums[i+1]:
items.append(i+1)
res = [i for i, j in enumerate(nums) if i not in items]
# [1, 2, 3]
(Python 3.6)
If you want remove all duplicate and keep the ordering:
>>> a = [1, 1, 2, 2, 2, 3, 4, 6, 3 ]
>>> list(dict.fromkeys(a))
[1, 2, 3, 4, 6]
But it will remove the last 3 too.
You can track array from end to start by length-1 like this:
nums = [1,2,2,2,3,3]
length = len(nums)
for i in reversed(range(length-1)):
while (nums[i] == nums[i-1]):
del(nums[i])
print(nums)

Editing a List From Inside a For Loop

Let's say I have a list, mylist, and I define it to be [1, 2, 3, 4, 5]. How is there a simple way to double every element of the list from within a for loop?
I know you could do something like:
for i in range(len(mylist)):
mylist[i] *= 2
I also know that you could make a list comprehension:
mylist = [2*i for i in range(1, 6)
But is there a way to do it like this?
for num in mylist:
#code goes here
I tried doing something like:
for num in mylist:
num *= 2
but num is a local variable, so this doesn't modify mylist, just num. Does anyone know a good way to do this?
The usual way to do this is with a list comprehension, iterating directly over the list items, not indirectly via an index.
mylist = [1, 2, 3, 4, 5]
mylist = [2 * num for num in mylist]
print(mylist)
output
[2, 4, 6, 8, 10]
That replaces mylist with a new list object. That's generally ok, but sometimes you want to modify the existing object, eg when other objects have a reference to mylist. You can do that with a slice assignment.
mylist[:] = [2 * num for num in mylist]
It's not really possible since you shouldn't try to change a list while looping through it in that way. I would stick with your other two ways of manipulating the list
Using an explicit for loop. Use enumerate while iterating and assign a new value to each item.
mylist = [1, 2, 3, 4, 5]
for i, n in enumerate(mylist):
mylist[i] = n * 2
Just be careful - don't change the number of items in a list: Remove items from a list while iterating

Categories