Why is for loop not printing as expected in Python? - python

I am new to python. I was learning the syntax of the for loop in python as:
for var in list_name:
# do something
I took a list:
list = [1,2,3,4,5,6,7,8,9]
I wanted to double each of its elements, so I run a loop as:
for i in list :
index = list.index(i)
list[index] = 2*i
print(list)
Then it prints:
[16,2,12,4,10,6,14,8,18]
I am not getting why it is printing like this?

Let's run through the first few iterations of your loop.
Iteration 1: i is 1.
index = list.index(i)
list[index] = 2*i
index is 0, and list[0] is set to 2*i. The list now looks like [2, 2, 3, 4, 5, 6, 7, 8, 9].
Iteration 2: i is 2.
index = list.index(i)
list.index(2) finds the first occurrence of 2 in the list, which is at index 0! There's more than one 2, and you're not selecting the right one.
list[index] = 2*i
You double the wrong element!
This happens again on iterations 4, 6, and 8.
If you want to double the elements of a list, the easiest way is to make a new list with a list comprehension:
l = [2*i for i in l]
If you need the indices of the elements in a for loop, the best way is usually to enumerate the list:
for i, item in enumerate(l):
whatever()
Also, don't call your list list, or when you try to call the list function, you'll get a weird TypeError.

Your code doesn't work as you expected, because list.index will return the first index of the element in the list. So, if the same element occurs more than once, it will not work as you expected.
The best way to double elements is to use list comprehension, like this
my_list = [item * 2 for item in my_list]
If you want to use a for loop, you can use enumerate, like this
for index, current_num in enumerate(my_list):
my_list[index] = current_num * 2
This is ugly because we are modifying the list as we iterate it. So, don't do this. Instead you can do like this
for index in xrange(len(my_list)):
my_list[index] *= 2

list.index(i) returns the first index in the list where i is found.
thelist = [1,2,3,4,5,6,7,8,9]
> index = thelist.index(1)
> index = 0
> thelist[0] = 2
> index = thelist.index(2)
> index = 0
> thelist[0] = 2*2 = 4
> index = thelist.index(3)
> index = 2
> thelist[2] = 2*3 = 6
> index = thelist.index(4)
> index = 0
> thelist[0] = 2*4 = 8
> index = thelist.index(5)
> index = 4
> thelist[4] = 2*5 = 10
> index = thelist.index(6)
> index = 2
> thelist[2] = 2*6 = 12
> index = thelist.index(7)
> index = 6
> thelist[6] = 2*7 = 14
> index = thelist.index(8)
> index = 0
> thelist[0] = 2*8 = 16
> index = thelist.index(9)
> index = 8
> thelist[8] = 2*9 = 18
and the rest of the elements will remain unaltered.
Also, it is incorrect to use a keyword as a variable name. You should NOT use list as a variable name.

print map(lambda x: x*2, my_list)

Because you're altering the wrong element of your list each time. The syntax for i in list set the value of one element of the list, not an index.
In fact, you shouldn't altering the list you're working on but creating a new list. A correct way would be:
new_list = []
for i in list:
new_list.append(2*i)
# Or even, with a list comprehension
new_list = [i*2 for i in list]
print(new_list)

Related

Python ( iteration problem ) with an exercice

The code :
import pandas as pd
import numpy as np
import csv
data = pd.read_csv("/content/NYC_temperature.csv", header=None,names = ['temperatures'])
np.cumsum(data['temperatures'])
printcounter = 0
list_30 = [15.22]#first temperature , i could have also added it by doing : list_30.append(i)[0] since it's every 30 values but doesn't append the first one :)
list_2 = [] #this is for the values of the subtraction (for the second iteration)
for i in data['temperatures']:
if (printcounter == 30):
list_30.append(i)
printcounter = 0
printcounter += 1
**for x in list_30:
substract = list_30[x] - list_30[x+1]**
list_2.append(substraction)
print(max(list_2))
Hey guys ! i'm really having trouble with the black part.
**for x in list_30:
substract = list_30[x] - list_30[x+1]**
I'm trying to iterate over the elements and sub stracting element x with the next element (x+1) but the following error pops out TypeError: 'float' object is not iterable. I have also tried to iterate using x instead of list_30[x] but then when I use next(x) I have another error.
for x in list_30: will iterate on list_30, and affect to x, the value of the item in the list, not the index in the list.
for your case you would prefer to loop on your list with indexes:
index = 0
while index < len(list_30):
substract = list_30[index] - list_30[index + 1]
edit: you will still have a problem when you will reach the last element of list_30 as there will be no element of list_30[laste_index + 1],
so you should probably stop before the end with while index < len(list_30) -1:
in case you want the index and the value, you can do:
for i, v in enumerate(list_30):
substract = v - list_30[i + 1]
but the first one look cleaner i my opinion
if you`re trying to find ifference btw two adjacent elements of an array (like differentiate it), you shoul probably use zip function
inp = [1, 2, 3, 4, 5]
delta = []
for x0,x1 in zip(inp, inp[1:]):
delta.append(x1-x0)
print(delta)
note that list of deltas will be one shorter than the input

How to find steps in a vector (1d array, list) in Python?

I want to get border of data in a list using python
For example I have this list :
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
I want a code that return data borders. for example:
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
^ ^ ^ ^
b = get_border_index(a)
print(b)
output:
[0,4,7,12]
How can I implement get_border_index(lst: list) -> list function?
The scalable answer that also works for very long lists or arrays is to use np.diff. In that case you should avoid a for loop at all costs.
import numpy as np
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
a = np.array(a)
# this is unequal 0 if there is a step
d = np.diff(a)
# boolean array where the steps are
is_step = d != 0
# get the indices of the steps (first one is trivial).
ics = np.where(is_step)
# get the first dimension and shift by one as you want
# the index of the element right of the step
ics_shift = ics[0] + 1
# and if you need a list
ics_list = ics_shift.tolist()
print(ics_list)
You can use for loop with enumerate
def get_border_index(a):
last_value = None
result = []
for i, v in enumerate(a):
if v != last_value:
last_value = v
result.append(i)
return result
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
b = get_border_index(a)
print(b)
Output
[0, 4, 7, 12]
This code will check if an element in the a list is different then the element before and if so it will append the index of the element to the result list.

python for and while loop for tuples

I'm a beginner in python and was wondering why this function doesn't work. It is syntactically correct.
This function is supposed to collect every odd tuple item and I used a for loop as follows:
def oddTuples(aTup):
result = ()
for i in aTup:
if i % 2 == 0:
result += (aTup[i],)
return result
This is the 'correct' answer using while loop.
def oddTuples(aTup):
# a placeholder to gather our response
rTup = ()
index = 0
# Idea: Iterate over the elements in aTup, counting by 2
# (every other element) and adding that element to
# the result
while index < len(aTup):
rTup += (aTup[index],)
index += 2
return rTup
If anybody can help me, it would be much appreciated!
UPDATE
Okay, I got the problem, by 'i' I was merely collecting the real value within that tuple. I've fixed that, but this code is catching only some of the odd-idexed items, not all of them....
def oddTuples(aTup):
result = ()
for i in aTup:
index = aTup.index(i)
if index % 2 == 0:
result += (aTup[index],)
return result
Your for loop is iterating over the values in aTup, not the index of the values.
It appears your want your code to iterate over the index of the values or through a range of numbers starting with 0 and ending with the length of the tuple minus one and then use that number as the index to pull the value out of the tuple.
I didn't catch it on one go since it was syntactically correct too, but the error you are having is due to you iterating over the objects of the tuple (aTup) and not the indices. See here:
for i in aTup: # <-- For each *object* in the tuple and NOT indices
if i % 2 == 0:
result += (aTup[i],)
To fix the problem, use range() and len() over the aTup so that it iterates over the indices of the tuple instead, and change the if statement accordingly:
for i in range(len(aTup)):
if aTup[i] % 2 == 0:
result += (aTup[i],)
An alternative solution is to keep your object iterations but append the object directly to the result tuple instead of indexing:
for i in aTup:
if i % 2 == 0:
result += (i,)
Hope ths helped!
The reason is you are not using index..In below code i is not an index but the element in tuple but you are calling aTup[i] assuming i is an index which is not.
The below code will work fine - No need of doing aTup[i] or range.
def oddTuples(aTup):
result = ()
for i in aTup:
if i % 2 == 0:
result += (i,)
return result
Try replacing
def oddTuples(aTup):
result = ()
for i in aTup:
index = aTup.index(i)
if index % 2 == 0:
result += (aTup[index],)
return result
With
def oddTuples(aTup):
result = ()
for i in aTup:
index = aTup.index(i)
result += (aTup[index],)
return result
To fix you issue of it only doing the even numbered ones.
In simple words , if your tuple is
tup = (1, 2, 3, 4, 5 , 1000);
When your code is checking if each item is % 2 == 0 or not which is not what you want, from your description , you want only the items with odd index
So if you try the tuple above , you will get the following error:
IndexError: tuple index out of range , because for the 1000 it satisfy your condition and will do what is said in the if , trying to add the aTup(1000) (element of index 1000 in your input tuple) which doesn't exist as the tuple is only of 6 elements to your resultTuple
For this for loop to work , you can use the following method
def oddTuples(aTup):
result = ()
for i in aTup:
index = tup.index(i) # getting the index of each element
if index % 2 == 0:
result += (aTup[index],)
print(aTup[index])
return result
# Testing the function with a tuple
if __name__ == "__main__":
tup = (1, 2, 3, 7, 5, 1000, 1022)
tup_res = oddTuples(tup)
print(tup_res)
The result of this will be
1
3
5
1022
(1, 3, 5, 1022)
Process finished with exit code 0

Finding if the next element is smaller than the one before it and deleting it from the list python

I am having trouble with my code, I am writing a method that will check if the next element is smaller than the previous element and if it is, it will delete it.
Example:
Input: [1, 20, 10, 30]
Desired output: [1,20,30]
Actual output: [30]
def findSmaller(s):
i = -1
y = []
while i <= len(s):
for j in range(len(s)):
if s[i+1] <= s[i]:
del s[i + 1]
y.append(s[i])
i += 1
return y
If you are uncertain about how your loops work I recommend adding in some print statements. That way you can see what your loop is actually doing, especially in more complicated problems this is useful.
Something like this would solve your problem.
a = [1,2,3,2,4]
for k in range(0,len(a)-2): #-2 so that one don't go past the loops length
#print(k)
y = a
if(a[k]>a[k+1]):
del y[k+1] #delete the k+1 element if it is
>>> s = [5, 20, 10, 15, 30]
>>> max_so_far = s[0]
>>> result = []
>>> for x in s:
if x >= max_so_far:
result.append(x)
max_so_far = x
>>> result
[5, 20, 30]
Depending whether you need to do some calculation later with the list you can use a generator
s = [1, 20, 10, 30]
def find_smaller_generator(l: list):
last_item = None
for item in l:
if last_item is None or item >= last_item:
last_item = item
yield item
def find_smaller_list(l: list):
return list(find_smaller_generator(l))
print(find_smaller_list(s))
for i in find_smaller_generator(s):
print(i)
print([i**2 for i in find_smaller_generator(s)])
this returns:
[1, 20, 30]
1
20
30
[1, 400, 900]
You can try something like this
def findSmaller(s):
# sets p (previous) as the first value in s
p = s[0]
# initializes y to be an array and sets the first value to p
y = [p]
# iterates over s, starting with the second element
for i in s[1::]:
# checks if i is greater than or equal to the previous element
if i >= p:
# if it is, i is appended to the list y
y.append(i)
# also set the previous value to i, so the next iteration can check against p
p = i
#returns the list
return y
What this does is iterate over s and checks if the current item in the list is greater than or equal to the previous element in the list. If it is then it appends it to y, and y is returned.
Try out the code here.

Smallest Number in a List - Python

I am trying to write a function that takes a list input and returns the index of the smallest number in that list.
For example,
minPos( [5,4,3,2,1] ) → 4
When I run my function, I get a List Index error, can someone please help? Thanks. I cannot use the built in function min().
def MinPos(L):
Subscript = 0
Hydrogen = 1
SmallestNumber = L[Subscript]
while L[Subscript] < len(L):
while L[Subscript] < L[Subscript + Hydrogen]:
Subscript += 1
return SmallestNumber
while L[Subscript] > L[Subscript + Hydrogen]:
Subscript += 1
return SmallestNumber
def main():
print MinPos( [-5,-4] )
Maybe something like this:
>>> def min_pos(L):
... min = None
... for i,v in enumerate(L):
... if min is None or min[1] > v:
... min = (i,v)
... return min[0] if min else None
>>> min_pos([1,3,4,5])
0
>>> min_pos([1,3,4,0,5])
3
Edit: Return None if empty list
Since you already know how to find the minimum value, you simply feed that value to the index() function to get the index of this value in the list. I.e,
>>> n = ([5,4,3,2,1])
>>> n.index(min(n))
4
This will return the index of the minimum value in the list. Note that if there are several minima it will return the first.
I would recommend use of for ... and enumarate():
data = [6, 3, 2, 4, 2, 5]
try:
index, minimum = 0, data[0]
for i, value in enumerate(data):
if value < minimum:
index, minimum = i, value
except IndexError:
index = None
print index
# Out[49]: 2
EDIT added guard against empty data

Categories

Resources