Out of range index - python

I am trying to make a program that will count the numbers in the list number, and would search for a sum of 10 in sequence_len numbers.
In the minute it gets a 10, it should stop.
1. With this code I have an error. what should I do?
total=total+(list_n[i+n])
IndexError: list index out of range
2.I want the first for to be stop if Im finding a sum of then. Is it write to "break" at the end as I did or should I write i=len(list_n)?
number = 1234
sequence_len = 2
list_n=[]
total=0
b="false"
list_t=[]
for j in str(number):
list_n.append(int(j))
c=len(list_n)
for i in list_n:
n=0
while n<sequence_len:
total=total+(list_n[i+n])
n=n+1
if total==10:
b=true
seq=0
while seq>sequence_len:
list_t.append(list_t[i+seq])
seq=seq+1
break
else:
total=0
if b=="true":
break
if b=="false":
print "Didn’t find any sequence of size", sequence_len
else:
print "Found a sequence of size", sequence_len ,":", list_t

You have a couple of errors. First with the basic:
b=true
This needs to the True, otherwise, python will look for the true variable.
Secondly, i actually contains the value of the variable for that iteration (loop). For example:
>>> l = ['a', 'b', 'c']
>>> for i in l: print i
a
b
c
Because of this, you cannot use it as an index, as indexes have to be integers. So, what you need to do is use enumerate, this will generate a tuple of both the index and the value, so something like:
for i, var in enumerate(list_n):
n = 0
An example of enumerate in action:
>>> var = enumerate([1,6,5,32,1])
>>> for x in var: print x
(0, 1)
(1, 6)
(2, 5)
(3, 32)
(4, 1)
And this statement should has logical problems I believe:
total = total + (list_n[i + n - 1])
If you want to get a sum of 10 from a list of numbers, you can use this brute-force technique:
>>> list_of_n = [1,0,5,4,2,1,2,3,4,5,6,8,2,7]
>>> from itertools import combinations
>>> [var for var in combinations(list_of_n, 2) if sum(var) == 10]
[(5, 5), (4, 6), (2, 8), (2, 8), (3, 7), (4, 6), (8, 2)]
So, if you want a 10 from 3 numbers in the list, you would put combinations(list_of_n, 3) instead of combinations(list_of_n, 2).

When you say
for i in list_n:
i will not refer to the indices, but to the list elements themselves. If you want just the indices,
for i in range(len(list_n)):
len(list_n) will give you the size of the list and range(len(list_n)) will give you a range of numbers starting from 0 and ending with len(list_n) - 1

Related

I'm not able to understand this code in tuple

init_tuple = [(0, 1), (1, 2), (2, 3)]
result = sum(n for _, n in init_tuple)
print(result)
The output for this code is 6. Could someone explain how it worked?
Your code extracts each tuple and sums all values in the second position (i.e. [1]).
If you rewrite it in loops, it may be easier to understand:
init_tuple = [(0, 1), (1, 2), (2, 3)]
result = 0
for (val1, val2) in init_tuple:
result = result + val2
print(result)
The expression (n for _, n in init_tuple) is a generator expression. You can iterate on such an expression to get all the values it generates. In that case it reads as: generate the second component of each tuple of init_tuple.
(Note on _: The _ here stands for the first component of the tuple. It is common in python to use this name when you don't care about the variable it refers to (i.e., if you don't plan to use it) as it is the case here. Another way to write your generator would then be (tup[1] for tup in init_tuple))
You can iterate over a generator expression using for loop. For example:
>>> for x in (n for _, n in init_tuple):
>>> print(x)
1
2
3
And of course, since you can iterate on a generator expression, you can sum it as you have done in your code.
To get better understanding first look at this.
init_tuple = [(0, 1), (1, 2), (2, 3)]
sum = 0
for x,y in init_tuple:
sum = sum + y
print(sum)
Now, you can see that what above code does is that it calculate sum of second elements of tuple, its equivalent to your code as both does same job.
for x,y in init_tuple:
x hold first value of tuple and y hold second of tuple, in first iteration:
x = 0, y = 1,
then in second iteration:
x = 1, y = 2 and so on.
In your case you don't need first element of tuple so you just use _ instead of using variable.

Assign a repeated sequence to an index in python

I am very new to python and I wanted to know, how can I assign an integer incrementally to every 3 values in a series. Might be better to explain with an example:
The result should contain the following pattern :
(1,1),(2,1),(3,1),(4,2),(5,2),(6,2),(7,3).......
Alternatively, just using a simple for loop and two variables:
val1 = 1
val2 = 1
for a in range(10): # this number is arbitrarily large
for b in range(3): # this number is not arbitrary
print( (val1, val2) )
val1 += 1
val2 += 1
You can use the floor division operator with a list comprehension:
n = range(1, 10)
res = [(i, idx//3 + 1) for idx, i in enumerate(n)]
print(res)
[(1, 1), (2, 1), (3, 1),
(4, 2), (5, 2), (6, 2),
(7, 3), (8, 3), (9, 3)]
If you want this to be infinite, I'd suggest looking into the utilities in itertools
from itertools import count
def integers_rep(n):
for i in count(1):
for _ in range(n):
yield i
def gen_sequence():
return zip(count(1), integers_rep(3))
count(n) is an iterable which will yield the sequence n, n+1, n+2, ... ad infinitum starting at it's first argument (which defaults to 0 if nothing is passed).
gen_sequence which would create your sequence, uses zip which takes N-iterables and produces a sequence of N-tuples (two sequences => pairs, three => triples, etc.). By taking count and the other sequence, you will be able to then get their pairs.
By using these tools, you would be able to define everything at a high level (which can be useful for mathematical sequences).

Python - how to find the position of the second lowest value in a list [duplicate]

This question already has answers here:
Finding the nth smallest number in a list?
(2 answers)
Closed 5 years ago.
I have the following list:
list = [7,3,6,4,6]
I know I can use list.index(min(list)) to find the position of the lowest number in the list, but how do I use it to find the second lowest?
don't use list as a var name
edit, originally misread as index of 2nd highest - fixed now, thanx Jean-François Fabre
lst = [7,3,6,4,6]
lst.index(sorted(lst)[1])
Out[161]: 3
lst[3]
Out[162]: 4
sorted(lst)
Out[163]: [3, 4, 6, 6, 7]
the above has a problem with repeated numbers in the input list, by using .index you get the index of the 1st match
lst = [1, 1, 7,3,6,4,6]
lst.index(sorted(lst)[1])
Out[9]: 0 # 0 is wrong, the postion of the 2nd smallest is 1
I think this fixes it
n = 1
sorted([*enumerate(lst)], key=lambda x: x[1])[n][0]
Out[11]: 1
looking at the pieces
[*enumerate(lst)]
Out[12]: [(0, 1), (1, 1), (2, 7), (3, 3), (4, 6), (5, 4), (6, 6)]
enumerate pairs a count with the values in the input lst, * forces 'unpacking' of the enumerate object, the outer sq brackets 'catch' this output in a list
inside Python builtin sorted the 2nd argument key=lambda x: x[1] tell it to look in the 2nd position of the tuples from [*enumerate(lst)] which are the numbers from lst
sorted([*enumerate(lst)], key=lambda x: x[1])
Out[13]: [(0, 1), (1, 1), (3, 3), (5, 4), (4, 6), (6, 6), (2, 7)]
the indexing that list with [n][0] gets the n-th sorted tuple, and takes the 1st value from the tuple which is the index asigned in enumerate
try this:
list.index(sorted(list)[1])
you could sort the enumerated list according to value, and pick the second item.
def second_pos(numbers):
return sorted(enumerate(numbers),key=lambda x:x[::-1])[1][0]
print(second_pos([7,3,6,4,6]))
result: 3, as 4 is the second lowest value
This solution involves one sort operation only, no index operation afterwards to find the index, saving that last O(n) operation.
Note that there's a tiebreaker picking the lowest positionned item in case 2 values are equal.
Also note that if the list is too small, you can get an IndexError
Use set to get rid of duplicates, like this
lowest_nth = 2
lst.index(sorted(set(lst))[lowest_nth-1])
Edit (important remark):
If you try with this code, will see a wrong result with duplicated values if set is not used:
lst = [7, 6, 6, 4, 3, 8]
def get_index_without_using_set():
return lst.index(sorted(lst)[lowest_nth-1])
def get_index_using_set():
return lst.index(sorted(set(lst))[lowest_nth-1])
print(lst)
print()
print('Without set:')
for lowest_nth in range(1,6):
print('lowest {}: {}'.format(lowest_nth, get_index_without_using_set()))
print()
print('With set:')
for lowest_nth in range(1,6):
print('lowest {}: {}'.format(lowest_nth, get_index_using_set()))
Output:
[7, 6, 6, 4, 3, 8]
Without set:
lowest 1: 4
lowest 2: 3
lowest 3: 1
lowest 4: 1 <-- wrong index, see below
lowest 5: 0
With set:
lowest 1: 4
lowest 2: 3
lowest 3: 1
lowest 4: 0
lowest 5: 5
This seems appropriate:
def find_2nd_smallest(iterable):
try:
st = set(iterable)
st.discard(min(st))
return iterable.index(min(st))
except:
return None
my_list = [7,3,6,4,6]
print (find_2nd_smallest(my_list))
prints the index of the first occurrence of the 2nd smallest:
3
And if you want a function where you can input the number smallest (the 2 means 2nd smallest):
def find_nth_smallest(iterable,n):
try:
st = set(iterable)
for i in range(n-1):
st.discard(min(st))
return iterable.index(min(st))
except: return None
my_list = [7,3,6,4,6]
print (find_nth_smallest(my_list,2))
Please note these functions may not be the most efficient solutions.
You can just remove the min and then get the min of the new list that has a new min , which would be the second min. I made a copy of the list so it would work but probably don't need to do that.
lst_copy = list(lst)
lst.remove(min(lst))
lst_copy.index(min(lst))

Python- For Loop - Increment each index position for each tuple in list

I've searched around for a possible way to do this. I'm trying to make a loop that will go through my list of tuple pairs. Each index contains data that I will calculate and append to a list through each loop run until the end of the list of tuples is reached. Currently using a for loop, but I might use while loop.
index_tuple = [(1, 2), (2, 3), (3, 4)]
total_list = []
for index_pairs in index_tuple:
total_list.append(index_tuple[0][1] - index_tuple[0][0])
What I'm trying to get the loop to do:
(index_tuple[0][1] - index_tuple[0][0])#increment
(index_tuple[1][1] - index_tuple[1][0])#increment
(index_tuple[2][1] - index_tuple[2][0])#increment
Then I guess my final question is it possible to increment index position with a while loop?
Use a list comprehension. This iterates the list, unpacks each tuple to two values a and b, then it subtracts the first item from the second and inserts this new subtracted value into the new list.
totals = [b - a for a, b in index_tuple]
A list comprehension is the best solution for this problem, and Malik Brahimi's answer is the way to go.
Nevertheless, sticking with your for loop, you need to reference index_pairs in the body of the loop because this variable is assigned each tuple from index_tuple as the loop iterates. You do not need to maintain an index variable. A corrected version would be this:
index_tuple = [(1, 2), (2, 3), (3, 4)]
total_list = []
for index_pairs in index_tuple:
total_list.append(index_pairs[1] - index_pairs[0])
>>> print total_list
[1, 1, 1]
A cleaner version which unpacks the tuples from the list directly into 2 variables would be:
index_tuples = [(1, 2), (2, 3), (3, 4)]
total_list = []
for a, b in index_tuples:
total_list.append(b - a)
>>> print total_list
[1, 1, 1]
You also asked about using a while loop to achieve the same. Use an integer to keep track of the current index and increment it by one on each iteration of the loop:
index_tuples = [(1, 2), (2, 3), (3, 4)]
total_list = []
index = 0
while index < len(index_tuples):
total_list.append(index_tuples[index][1] - index_tuples[index][0])
index += 1
>>> print total_list
[1, 1, 1]

making list in python

When i executed the following python script
list= (1,2,3,4,1,2,7,8)
for number in list:
item1= number
item2= list[list.index(item1)+2]
couple= item1, item2
print couple
the goal is to link each number with the second following
I obtain this result
(1, 3)
(2, 4)
(3, 1)
(4, 2)
(1, 3)
(2, 4)
(and then the index gets out of range but this is not the problem)
My question is why the number 1 in the fifth line is still coupled to the number 3 and how can i make that it is coupled to the number 7; idem for the number 2 in the sixth line that should be coupled to the number 8.
additional question
what do I do if i only want to make a list of the couples that start with 1: [(1,3), (1,7)]
list.index returns the offset of the first occurrence of the value in the list - thus if you do [1,1,1].index(1), the answer will always be 0, even though 1 and 2 are also valid answers.
Instead, try:
from itertools import islice, izip, ifilter
mylist = [1,2,3,4,1,2,7,8]
for pair in ifilter(lambda x: x[0]==1, izip(mylist, islice(mylist, 2, None))):
print pair
results in
(1, 3)
(1, 7)
xs.index(x) gives you the index of the first occurence of x in xs. So when you get to the second 1, .index gives you the index of the first 1.
If you need the index alongside the value, use enumerate: for i, number in enumerate(numbers): print number, numbers[i+2].
Note that I deliberately didn't use the name list. It's the name of a built-in, you shouldn't overwrite it. Also note that (..., ...) is a tuple (and therefore can't be changed), not a list (which is defined in square brackets [..., ...] and can be changed).
You have duplicates in the list so index always returns the first index.
Start your program with for index in range(len(list) - 1)
You are using .index which returns the first occurrence of number.
consider:
for number in range(len(list)):
item1= list[number]
item2= list[number+2]
couple= item1, item2
print couple
>>> zip(lst, lst[2:])
[(1, 3), (2, 4), (3, 1), (4, 2), (1, 7), (2, 8)]
To get only pairs (1, X):
>>> [(a, b) for (a, b) in zip(lst, lst[2:]) if a == 1]
[(1, 3), (1, 7)]
Recommended reading:
http://docs.python.org/tutorial/datastructures.html
http://docs.python.org/howto/functional.html

Categories

Resources