When I try to run my code, I seem to run with an IndexError - python-3.x

When I try to run my code, I seem to run with an IndexError.
def _init_trellis(self, observed, forward=True, init_func=identity):
trellis = [ [None for j in range(len(observed))]
for i in range(len(self.real_states) + 1) ]
if forward:
v = lambda s: self.transition(0, s) * self.emission(s, observed[1])
else:
v = lambda s: self.transition(s, self.end_state)
init_pos = 1 if forward else -1
for state in self.state_nums():
trellis[state][init_pos] = init_func( v(state) )
return trellis
ERROR:
v = lambda s: self.transition(0, s) * self.emission(s, observed[1]) IndexError: list index out of range

Add assertions to your code.
assert(len(observed) > 1)
will ensure that the array is long enough.

Update:
This happens when you try to access a list with an index, but the list does not have that many elements to show.
For example:
a_list = ['a', 'b', 'c']
print(a_list[0] # Prints a.
print(a_list[2] # Prints c.
print(a_list[3] # Gives IndexError.
'''Index of 3 means the 4th element of the list is being accessed.
Since the list only has 3 elements, it gives an index error.'''
In this case, observed[1] giving an index error means observed has only 1 element.
That is, len(observed) is 1.
Original Answer:
Based on the error, ensure that observed is an iterable with a minimum length of 2.

Related

comparing int value in list throws index out of range Error

I'm struggling to grasp the problem here. I already tried everything but the issue persist.
Basically I have a list of random numbers and when I try to compare the vaalues inside loop it throws "IndexError: list index out of range"
I even tried with range(len(who) and len(who) . Same thing. When put 0 instead "currentskill" which is int variable it works. What I don't understand is why comparing both values throws this Error. It just doesn't make sence...
Am I not comparing a value but the index itself ???
EDIT: I even tried with print(i) / print(who[i] to see if everything is clean and where it stops, and I'm definitelly not going outside of index
who = [2, 0, 1]
currentskill = 1
for i in who:
if who[i] == currentskill: # IndexError: list index out of range
who.pop(i)
The problem is once you start popping out elements list size varies
For eg take a list of size 6
But you iterate over all indices up to len(l)-1 = 6-1 = 5 and the index 5 does not exist in the list after removing elements in a previous iteration.
solution for this problem,
l = [x for x in l if x]
Here x is a condition you want to implement on the element of the list which you are iterating.
As stated by #Hemesh
The problem is once you start popping out elements list size varies
Problem solved. I'm just popping the element outside the loop now and it works:
def deleteskill(who, currentskill):
temp = 0
for i in range(len(who)):
if who[i] == currentskill:
temp = i
who.pop(temp)
There are two problems in your code:
mixing up the values and indexes, as pointed out by another answer; and
modifying the list while iterating over it
The solution depends on whether you want to remove just one item, or potentially multiple.
For removing just one item:
for idx, i in enumerate(who)::
if i == currentskill:
who.pop(idx)
break
For removing multiple items:
to_remove = []
for idx, i in enumerate(who)::
if i == currentskill:
to_remove.append[idx]
for idx in reversed(to_remove):
who.pop(idx)
Depending on the situation, it may be easier to create a new list instead:
who = [i for i in who if i != currentskill]
Your logic is wrong. To get the index as well as the value, use the built-in function enumerate:
idx_to_remove = []
for idx, i in enumerate(who)::
if i == currentskill:
idx_to_remove.append[idx]
for idx in reversed(idx_to_remove):
who.pop(idx)
Edited after suggestion from #sabik

List Index Error - Combining list elements via index

'Original String = 1234 A 56 78 90 B'
def func_1(one_dict):
global ends
ends = []
for x in original_string:
if x in one_dict:
ends.append(one_dict[x])
return ends
The above returns:
['B', 'A']
My next function is supposed to then combine them into 1 string and get value from dictionary. I've tried this with/without the str in mult_ends with the same result.
def func_2(two_dict):
global mult_ends
mult_ends = str(ends[0] + ends[1])
for key in mult_ends:
if key in two_dict:
return two_dict[key]
The results confuse me since I use pretty identical processes in other functions with no issue.
IndexError: list index out of range
Why would the list index be out of range when there is clearly a 0 and 1? I've also added global ends to func_2 and I still received the same error.
*** RESTRUCTURED FUNCTIONS INTO 1 ***
def func_1(one_dict):
global ends
ends = []
for x in original_string:
if x in one_dict:
ends.append(one_dict[x])
mult_ends = ends[0] + ends[1]
for key in two_dict:
if key in mult_ends:
return ends_final_dict[key]
return None
Now, it actually does what I want it to do and returns the correct dictionary key in the event log:
A B
However, it does not return when I try to insert it back into my GUI for the user and it still throws the IndexError: list index out of range.

Number of sub sequences of length K having total sum S, given 2d array

I wish to find Number of sub sequences of length K having total sum S, given an array.
Sample Input:
a=[1,1,1,2,2] & K=2 & S=2
Sample Output:
3 {because a[0],a[1]; a[1]a[2]; a[0]a[2] are only three possible for the case}
I have tried to write a recursive loop in Python for starter but it isn't giving output as expected.Please can you help me find a loophole I might be missing on.
def rec(k, sum1, arr, i=0):
#print('k: '+str(k)+' '+'sum1: '+str(sum1)) #(1) BaseCase:
if(sum1==0 and k!=0): # Both sum(sum1) required and
return 0 # numbers from which sum is required(k)
if(k==0 and sum1 !=0): # should be simultaneously zero
return 0 # Then required subsequences are 1
if(k==0 and sum1==0 ): #
return 1 #
base_check = sum1!=0 or k!=0 #(2) if iterator i reaches final element
if(i==len(arr) and base_check): # in array we should return 0 if both k
return 0 # and sum1 aren't zero
# func rec for getting sum1 from k elements
if(sum1<arr[0]): # takes either first element or rejects it
ans=rec(k-1,sum1,arr[i+1:len(arr)],i+1) # so 2 cases in else loop
print(ans) # i is taken in as iterator to provide array
else: # input to rec func from 2nd element of array
ans=rec(k-1, sum1-arr[0], arr[i+1:len(arr)],i+1)+rec(k, sum1, arr[i+1:len(arr)],i+1)
#print('i: '+str(i)+' ans: '+str(ans))
return(ans)
a=[1,1,1,2,2]
print(rec(2,2,a))
I am still unable to process how to make changes. Once this normal recursive code is written I might go to DP approach accordinlgy.
Using itertools.combinations
Function itertools.combinations returns all the subsequences of a given lengths. Then we filter to keep only subsequences who sum up to the desired value.
import itertools
def countsubsum(a, k, s):
return sum(1 for c in itertools.combinations(a,k) if sum(c)==s)
Fixing your code
Your code looks pretty good, but there are two things that appear wrong about it.
What is this if for?
At first I was a bit confused about if(sum1<arr[0]):. I think you can (and should) always go to the else branch. After thinking about it some more, I understand you are trying to get rid of one of the two recursive calls if arr[0] is too large to be taken, which is smart, but this makes the assumption that all elements in the array are nonnegative. If the array is allowed to contain negative numbers, then you can include a large a[0] in the subsequence, and hope for a negative element to compensate. So if the array can contain negative numbers, you should get rid of this if/else and always execute the two recursive calls from the else branch.
You are slicing wrong
You maintain a variable i to remember where to start in the array; but you also slice the array. Pretty soon your indices become wrong. You should use slices, or use an index i, but not both.
# WRONG
ans=rec(k-1, sum1-arr[0], arr[i+1:len(arr)],i+1)+rec(k, sum1, arr[i+1:len(arr)],i+1)
# CORRECT
ans = rec(k-1, sum1-arr[i], arr, i+1) + rec(k, sum1, arr, i+1)
# CORRECT
ans = rec(k-1, sum1-arr[0], arr[1:]) + rec(k, sum1, arr[1:])
To understand why using both slicing and an index gives wrong results, run the following code:
def iter_array_wrong(a, i=0):
if (a):
print(i, a)
iter_array_wrong(a[i:], i+1)
def iter_array_index(a, i=0):
if i < len(a):
print(i, a)
iter_array_index(a, i+1)
def iter_array_slice(a):
if a:
print(a)
iter_array_slice(a[1:])
print('WRONG')
iter_array_wrong(list(range(10)))
print()
print('INDEX')
iter_array_index(list(range(10)))
print()
print('SLICE')
iter_array_slice(list(range(10)))
Also note that a[i:len(a)] is exactly equivalent to a[i:] and a[0:j] is equivalent to a[:j].
Clean version of the recursion
Recursively count the subsequences who use the first element of the array, and the subsequences who don't use the first element of the array, and add the two counts. To avoid explicitly slicing the array repeatedly, which is an expensive operation, we keep a variable start to remember we are only working on subarray a[start:].
def countsubsum(a, k, s, start=0):
if k == 0:
return (1 if s == 0 else 0)
elif start == len(a):
return 0
else:
using_first_element = countsubsum(a, k-1, s-a[start], start+1)
notusing_first_elem = countsubsum(a, k, s, start+1)
return using_first_element + notusing_first_elem

Python generator that returns group of items

I am trying to make a generator that can return a number of consecutive items in a list which "moves" only by one index. Something similar to a moving average filter in DSP. For instance if I have list:
l = [1,2,3,4,5,6,7,8,9]
I would expect this output:
[(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7),(6,7,8),(7,8,9)]
I have made code but it does not work with filters and generators etc. I am afraid it will also break due to memory if I need to provide a large list of words.
Function gen:
def gen(enumobj, n):
for idx,val in enumerate(enumobj):
try:
yield tuple(enumobj[i] for i in range(idx, idx + n))
except:
break
and the example code:
words = ['aaa','bb','c','dddddd','eeee','ff','g','h','iiiii','jjj','kk','lll','m','m','ooo']
w = filter(lambda x: len(x) > 1, words)
# It's working with list
print('\nList:')
g = gen(words, 4)
for i in g: print(i)
# It's not working with filetrs / generators etc.
print('\nFilter:')
g = gen(w, 4)
for i in g: print(i)
The list for does not produce anything. The code should break because it is not possible to index a filter object. Of course one of the answers is forcing a list: list(w). However, I am looking for better code for the function. How can I change it so that function can accept filters as well etc. I am worried about memory to a huge number of data in a list.
Thanks
With iterators you need to keep track of values that have already been read. An n sized list does the trick. Append the next value to the list and discard the top item after each yield.
import itertools
def gen(enumobj, n):
# we need an iterator for the `next` call below. this creates
# an iterator from an iterable such as a list, but leaves
# iterators alone.
enumobj = iter(enumobj)
# cache the first n objects (fewer if iterator is exhausted)
cache = list(itertools.islice(enumobj, n))
# while we still have something in the cache...
while cache:
yield cache
# drop stale item
cache.pop(0)
# try to get one new item, stopping when iterator is done
try:
cache.append(next(enumobj))
except StopIteration:
# pass to emit progressively smaller units
#pass
# break to stop when fewer than `n` items remain
break
words = ['aaa','bb','c','dddddd','eeee','ff','g','h','iiiii','jjj','kk','lll','m','m','ooo']
w = filter(lambda x: len(x) > 1, words)
# It's working with list
print('\nList:')
g = gen(words, 4)
for i in g: print(i)
# now it works with iterators
print('\nFilter:')
g = gen(w, 4)
for i in g: print(i)

Function that prints each element of a list and its index per line

I am trying to write a function that can print the element and index of a list. I want to do this without using the enumerate built in function and do it using for loops.
I was able to print out the element but I couldn't figure out a way to loop the index of my list.
Is there any good way I could work around this? Many thanks.
You could do this, simply iterating over the range of numbers regarding the length of your list:
def item_and_index(my_list):
for i in range(len(my_list)):
print(my_list[i], i)
This is exactly what you need, a function using for loops and not the enumerate function.
>>> L = ['a', 'b', 'c']
>>> for i in range(len(L)):
... print(i, L[i])
...
0 a
1 b
2 c
You could also try this:
i = 0
for elem in L:
print(i, elem)
i += 1

Resources