Python - List index out of range, "for" loop - python

I don't get how a "for" loop that iterates through the elements of a list can be out of range.
First part seems to be okay as I can print it.
import random
def random_list(n):
l = []
for i in range(0,n):
l.append(random.randint(0,n))
return l
def maximum(n):
x = 0
b = random_list(n)
for i in b:
if b[i] > x:
x = b[i]
print (maximum(10))

This:
for i in b:
if b[i] > x:
x = b[i]
Iterates over the elements of b, not the indices. Change it to
for i in b:
if i > x:
x = i
You also need to return something from your function, probably x.

Considering that you know how to iterate over a list in python, the error could be due to randint, which generates an integer in the interval [low, high]. This means high is a possible output, while the highest index in your program is high - 1.
For example,
random.randint(0, 0)
gives 0.
Similarly, random.randint(10) can return 10.
If you don't understand how to iterate over a list in Python, consider a simple example:
Take the list below:
myList = [1, 3, 5, 7, 9]
Now, there are two ways to iterate over the list:
Directly accessing elements:
for element in myList:
print(element, end=" ")
This gives the output:
1 3 5 7 9
Accessing elements using indices
for idx in range(len(myList)):
print(idx, ":", myList[idx], end=" ")
This gives the output:
0:1 1:3 2:5 3:7 4:9

Related

How to get the number of the list in a list in Python 3?

I am trying to get the number of the nested list that contains the particular number. This is my code:
listo = [[1,2],[3,4,5]]
for x in listo:
if 3 in x:
print(len(x))
What I am trying to get here is the number of the nested list that has 3 in it. My code is returning 3 because I am of the function len, which is only returning the number of items inside the nested list that has the number. The output should be:
2
Since the number 3 is located on the second nested list. The count starts from 1, not 0.
How can I get the proper output?
Use enumerate:
listo = [[1,2], [3,4,5]]
res = next(i for i, sublist in enumerate(listo) if 3 in sublist)
print(res) # -> 1
Note that Python is 0-index languange; the first element on a list has index number 0. That is why the code above returns 1. If you want to get 2, well, just add 1 to that or, ever better, use the optional start parameter of enumerate (enumerate(listo, 1)).
To make the above Error-proof1, you can specify a default value to be returned in case 3 is not on any sublist.
res = next((i for i, sublist in enumerate(listo) if 3 in sublist), 'N\A')
1 next raises StopIteration if it exhausts the iterable without finding something to return, unless a default value is provided.
Use enumerate specifying the start value as 1:
listo = [[1,2],[3,4,5]]
for i, x in enumerate(listo, 1):
if 3 in x:
print(i)
# 2
Use enumerate so as to get the index of the element in the array.
l1 = ["eat","sleep","repeat"]
# printing the tuples in object directly
for ele in enumerate(l1):
print ele
Output:
(0, 'eat')
(1, 'sleep')
(2, 'repeat')
The same can be used for the code above.
listo = [[1,2,3],[4,5]]
for ind,x in enumerate(listo):
if 3 in x:
print(ind)
You can use enumerate. But if you are very new to coding this simple code is good.
Keep an extra variable (count) which will keep track of the index of the current list.
listo = [[1,2],[3,4,5]]
count = 0
for x in listo:
count += 1
if 3 in x:
print(count)
Simply use enumerate(). enumerate() returns a (element count, element) pair:
for count, element in enumerate(listo):
if 3 in element:
print(count + 1)
# Account for one-based indexing

How do I find the number of times elements of a list occur in another list?

For example, I have two lists:
A=['a','b','c']
B=['a','a','b','c']
I want my output to look like:
[2,1,1]
Here is what I tried:
P=np.ndarray(shape=3, dtype=int)
count=0
d=0
for i in A:
for j in B:
if i==j:
count+=1
P[d]=count
d+=1
But I am getting
[2,3,4]
as output. What is going wrong?
Just use count method:
A=['a','b','c']
B=['a','a','b','c']
[B.count(x) for x in A]
The methods as suggested by #CarlesMitjans or #WillenVanOnsem are better solutions than this, but the reason your method does not work is that you need to initialise your count variable inside the first loop (and also indent the d+=1 line):
P = np.ndarray(shape=3, dtype=int)
count = 0
d = 0
for i in A:
count = 0
for j in B:
if i == j:
count += 1
P[d] = count
d += 1
which gives:
>>> P
array([2, 1, 1])
If the elements are hashable, you can simply use a counter you then transform back into a list. Like:
from collections import Counter
ctr = Counter(B)
result = [ctr[x] for x in A]
This generates:
>>> [ctr[x] for x in A]
[2, 1, 1]
This works in O(|A|+|B|) with |A| the numbers in A and |B| the numbers in B (given dictionary lookup works in O(1), which is nearly always the case).
If the elements can not be hashed (for instance lists, dictionaries, objects,...), then you can use #CharlesMitjans answer, which runs in O(|A|×|B|) (which tends to be less efficient, but then you cannot take advantage of hashing).

Changing the value of range during iteration in Python

>>> k = 8
>>> for i in range(k):
print i
k -= 3
print k
Above the is the code which prints numbers from 0-7 if I use just print i in the for loop.
I want to understand the above code how it is working, and is there any way we can update the value of variable used in range(variable) so it iterates differently.
Also why it always iterates up to the initial k value, why the value doesn't updated.
I know it's a silly question, but all ideas and comments are welcome.
You can't change the range after it's been generated. In Python 2, range(k) will make a list of integers from 0 to k, like this: [0, 1, 2, 3, 4, 5, 6, 7]. Changing k after the list has been made will do nothing.
If you want to change the number to iterate to, you could use a while loop, like this:
k = 8
i = 0
while i < k:
print i
k -= 3
i += 1
The expression range(k) is evaluated just once, not on every iteration. You can't set k and expect the range(k) result to change, no. From the for statement documentation:
The expression list is evaluated once; it should yield an iterable object.
You can use a while loop instead:
i = 0
k = 8
while i < k:
print i
i += 1
k -= 3
A while loop does re-evaluate the test each iteration. Referencing the while statement documentation:
This repeatedly tests the expression and, if it is true, executes the first suite
If you do want to change k and affect the loop you need to make sure you are iterating over mutable object. For example:
k = list(range(8))
for i in k:
print(i)
k.pop()
k.pop()
k.pop()
print(k)
Or alternatively:
k = list(range(8))
for i in k:
print(i)
k[:] = k[:-3]
print(k)
Both will result with
0
[0, 1, 2, 3, 4]
1
[0, 1]
you could do it like this ,I think, but I dont know if this is what you want.
def to_infinity():
index = 0
while True:
yield index
index += 1
for i in to_infinity():
print(i)

Indexing the largest element in the tuple

a = (3,4,11,12,5,2,7,8,6,9,10)
for i in range(len(a)):
b = a[i]
for x in range(2,15):
if b > x:
c = i
print(c)
Result
>>>
10
>>>
In the above example, i'm trying to extract the largest element from tuple a by comparing each element against a specific range (2-14).
The result of above example should be 3(the index of 12), but i'm getting 10.
Can someone tell me what's wrong with the codes
Why use for loops at all?
a = (3,4,11,12,5,2,7,8,6,9,10)
print(a.index(max(a)))
If you are looking for a local maximum in a specific range between 2 indexes.
startindex, endindex = 2, 14
b = a[startindex : endindex]
print(b.index(max(b)) + startindex)
If by range 2 to 14 you mean the values in tuple a instead of index range then this works for me. It will print index of first occurrence.
a = (3,4,11,12,5,2,7,8,6,9,10)
subsetTuple = tuple(item for item in a if item in range(2,14))
print(a.index(max(subsetTuple)))
Or you can do it in one line
a = (3,4,11,12,5,2,7,8,6,9,10)
print( max( enumerate(a), key = lambda pair: pair[1] if pair[1] in range( 2, 14) else False )[0] )
Your code just delivers the index of the last element, which is laying in your defined range (which is in fact at index 10).
You you need to store the local maximum and compare each new element against it (instead of using range(2,15).
I'm not that familar with python, but to get the index of the largest element this could be a solution:
a = (3,4,11,12,5,2,7,8,6,9,10)
localMaximum = 0
for i in range(len(a)):
b = a[i]
if b>localMaximum:
localMaximum = b
c = i
print(c)
You get 10 as result because your tuple has 11 elements and the index of the last is 10.
You set this index equal to c in the 2nd loop:
for x in range(2,15):
if b > x:
c = i
Because 10 is the last value of the tuple that is looped over, and b > x is True at least once for b = 10, c gets assigned the index of 10 (which is 10) and that the is what is printed at the end.
How would you correct the problem?
I would do something like this:
a = (3,4,11,12,5,2,7,8,6,9,10)
c = 0
for i in range(len(a)):
if a[i] in range(2, 15) and a[i] > a[c]:
c = i
print(c)
This prints 3
It just loops over the tuple, checks if the current value is in the range 2-15 AND if the value is greater than the previous highest value, if both are True it sets the current index as the new c
Output:

Getting difference from all possible pairs from a list Python

I have an int list with unspecified number. I would like to find the difference between two integers in the list that match a certain value.
#Example of a list
intList = [3, 6, 2, 7, 1]
#This is what I have done so far
diffList = []
i = 0
while (i < len(intList)):
x = intList[i]
j = i +1
while (j < len(intList)):
y = intList[j]
diff = abs(x-y)
diffList.append(diff)
j += 1
i +=1
#Find all pairs that has a difference of 2
diff = diffList.count(2)
print diff
Is there a better way to do this?
EDIT: Made changes to the codes. This is what I was trying to do. What I want to know is what else can I use besides the loop.
seems like a job for itertools.combinations
from itertools import combinations
for a, b in combinations(intList, 2):
print abs(a - b)
You could even turn this one into a list comprehension if you wanted to :)
[abs(a -b) for a, b in combinations(intList, 2)]
int_list = [3, 6, 2, 7, 1]
for x in int_list:
for y in int_list:
print abs(x - y)

Categories

Resources