I keep getting an "IndexError: string index out of range" error message when I try to execute this code:
#function countLetters(word,letter) should count the number of times
#a particular letter appears in a word.
def countLetters(word, letter):
count=0
wordlen=len(word)
num=0
wordletter=""
while(num<=wordlen):
wordletter=word[num]
if(wordletter==letter):
count=count+1
num=num+1
return count
print(countLetters("banana", "x"))#should print 0
print(countLetters("banana", "a"))#should print 3
print(countLetters("banana", "b"))#should print 1
The Error Message:
Traceback (most recent call last):
File "C:\Users\Charlie Chiang\Desktop\9G.py", line 17, in <module>
print(countLetters("banana", "x"))
File "C:\Users\Charlie Chiang\Desktop\9G.py", line 10, in countLetters
var=word[num]
IndexError: string index out of range
You take it one index too far:
while(num<=wordlen):
num must stay strictly below the length:
while num < wordlen:
because Python sequences are 0-based. A string of length 5 has indices 0, 1, 2, 3, and 4, not 5.
You are reaching one index too far:
while(num<=wordlen):
For a text "a" the len("a") is 1 and last letter can be reached by index 0. Your while condition allows trying index 1, which is not available.
Bonus: counting using Counter
Python stdlib collections provides excellent Counter:
>>> from collections import Counter
>>> Counter("banana").get("x", 0)
0
>>> Counter("banana").get("a", 0)
3
Fixing your code:
def countLetters(word, letter):
count=0
wordlen=len(word)
num=0
wordletter=""
#here, because the index access is 0-based
#you have to test if the num is less than, not less than or equal to length
#last index == len(word) -1
while(num<wordlen):
wordletter=word[num]
if(wordletter==letter):
count=count+1
num=num+1
return count
print(countLetters("banana", "x"))#should print 0
print(countLetters("banana", "a"))#should print 3
print(countLetters("banana", "b"))#should print 1
more elegant way:
str.count method
'banana'.count('x')
'banana'.count('a')
'banana'.count('b')
Because the index of the string starts at zero, the highest valid index will be wordlen-1.
The index start at 0, not 1.
Try changing:
wordletter = word[num-1]
Related
I am passing dot separated key as a argument. I have used split(".") and then print the value data. Here is my code:
desc = str(sys.argv[1])
st = desc.split(".")
i = 0
print (len(st))
for i in range(len(st)):
for ch in st:
st[i] = ch
print (st[i])
i += 1
print(i)
#print(data[st1][st2]..[stn])
I am getting the output as
3
db
1
dap
2
nodes
3
db
2
db
3
Traceback (most recent call last):
File "getvar.py", line 17, in <module>
st[i] = ch
IndexError: list assignment index out of range
I want the data[db][dap][nodes] which will give me the correct value. How should I proceed?
You are confusing 2 loops : for item in items and for i in range.
When you use i in range the max value in length -1 because indexes are zero based.
when you have used split st is an array of values so the line st[i] = ch is reloading the value back where is was read from.
Here I give both syntaxes of the loop. You will observe that print(st) before the loops gives the result that you want.
desc="10.12.45.35.66.28"
#desc = str(sys.argv[1])
st = desc.split(".")
print([st])
print ("length:",len(st))
for j in range(len(st)-1):
print (j," -> ", st[j])
i = 0
for ch in st:
st[i] = ch
print (i," -> ", st[i])
i += 1
pancake_sort sorts some numbers in descending order (flips the biggest number to top (end) of the array then back to the bottom), then prints the index at which it did that (+1). This means that the array [4,3,2,1,5] will flip from index 0 so that it becomes [5,1,2,3,4] and will print 1, then will flip from the index 1 and will become [5,4,3,2,1], and it will print 2. Once it has done all its flips, it should then print 0. I've tried to add the different parts of the arrays together (the part that flips and the part that stays the same), but it doesn't work. I get this output and error message:
1
1 Traceback (most recent call last):
File "/Users/khadijah/Documents/pypan.py", line 32, in <module>
pancake_sort(arr)
File "/Users/khadijah/Documents/pypan.py", line 19, in pancake_sort
mi = arr.index(max(arr[i:arr_len]))
ValueError: max() arg is an empty sequence
I know that it has something to do with the i in the mi value, but I think I need that there so that it only checks the numbers between i and arr_len. Using arr_len-1 doesn't work either. What do you think I'm doing wrong?
This is my code:
def pancake_sort(arr):
arr_len=len(arr)
i=0
for i in range(0,arr_len-1):
mi = arr.index(max(arr[i:arr_len]))
arr = arr[0:mi-1]+arr[mi::-1]
print()
if mi == arr_len-1:
print("1", end = " ")
else: print(mi+1, end = " ")
if i==0:
arr=arr[::-1]
else:
arr = arr[0:i-1]+arr[i::-1]
return arr
arr = [4,3,2,1,5]
pancake_sort(arr)
You can use subscript assignment with reversed() to "flip" the pancake:
def flipSort(A):
for i in range(len(A)-1):
p = A[i:].index(max(A[i:])) + i # index of max (to end)
if i==p: continue # nothing to flip, skip
A[i:p+1]=reversed(A[i:p+1]) # <-- here is how to flip a subrange
print(i+1,end=" ") # print index (why one-based?)
print("0")
output:
A = [4,3,2,1,5]
flipSort(A)
1 2 0
print(A)
[5, 4, 3, 2, 1]
you can use is :
def pancake_sort(arr):
cur = len(arr)
while cur > 1:
# Find the maximum number in arr
mi = arr.index(max(arr[0:cur]))
# Reverse from 0 to mi
arr = arr[mi::-1] + arr[mi + 1 : len(arr)]
# Reverse whole list
arr = arr[cur - 1 :: -1] + arr[cur : len(arr)]
cur -= 1
print(cur)
return arr
print(pancake_sort([4,3,2,1,5]))
I have created a dictionary by counting a list of positives words(positives.txt) over a list of tweets(tweets.txt).
Now im trying to print the top 5 used postitive words with respective scores.
I have managed to sort the scores and able to print the whole list of words with their scores, like:
(rest of list...)
wordx 5
wordy 28
wordz 35
My goal is to print (just) a top 3:
wordz 35
wordy 28
wordx 5
I tried giving indexes en subscripts at different places but keep getting error messages like:
Traceback (most recent call last):
print(word[3], score[3])
IndexError: string index out of range
print(word[0:5], score[0:5])
TypeError: 'int' object is not subscriptable
Current Code:
def positive_word(tweets, positives):
"""prints the top 5 most used positive words"""
x = {}
#for l in range(5):
for l in range(len(positives)):
x[positives[l]] = 0
#for m in range (5):
for m in range (len(tweets)):
#for n in range (5):
for n in range (len(positives)):
if positives[n] in tweets[m]:
x[positives[n]] += 1
for word, score in sorted(x.items(), key = lambda key : key[1]):
print(word, score)
This question already has answers here:
Why am I seeing "TypeError: string indices must be integers"?
(9 answers)
Closed 5 years ago.
import sys
a = int(sys.argv[1])
def count_holes(n):
dic = {'1':0, '2':0, '3':0, '4':1, '5':0, '6':1, '7':0, '8':2, '9':1}
l = str(n)
counter = 0
i = 1
for i in l:
while i != len(l):
counter = counter + dic[l[i]]
print(counter)
count_holes(a)
i got this:
counter = counter + dic[l[i]]
TypeError: string indices must be integers
You're making this too complicated. You're getting that TypeError because you are trying to use the characters of l to index l. But you don't need to index into l, just directly iterate over the chars in the number string.
Here's a repaired version of your code.
import sys
def count_holes(n):
dic = {'1':0, '2':0, '3':0, '4':1, '5':0, '6':1, '7':0, '8':2, '9':1}
counter = 0
for c in str(n):
counter += dic[c]
return counter
a = int(sys.argv[1])
print(count_holes(a))
Here's some test code:
for i in (12357, 4, 66, 8, 999):
print(i, count_holes(i))
and its output
12357 0
4 1
66 2
8 2
999 3
When you say i in l, i cycles through characters in the string l. So i is a string and can't be used as an index. You could enumerate() the string and use a second variable in the loop as your index.
If n somehow contains len(n) in it I could see how the while loop might exit but I'm not sure if that's what you are going for. Although i and len(l) are different types, so you have that going for you... Which is nice.
I have a while loop that is looping over a list trying to find the number 1. I have the code below and it loops over "almost" all the list but it does not find the index for value 1
numbers = [24, 10, 92, 28, 71, 1, 80, 70]
counter = 0
number_to_find = 1
def my_loop():
global counter
while counter > 6: #Also not sure while 7 doesn't work, says out of range?
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
counter = counter + 1
my_loop()
print my_loop()
This is a very confusing bit of code.
You print the output, but the function does not return anything. (It also prints things, but it does not return anything.)
The function has a while loop and also recurs upon itself. (There are some cases where this is appropriate, but this is not one of them.)
counter is initially 0, but your first check is if counter > 6. 0 is not greater than six. (This is not technically wrong, but very confusing.)
The value 1 is at index 5. Why are you looking for 6?
Once you have reached the desired index, you do not terminate the loop.
You can achieve what you're looking for using the following piece of code:
numbers = [24, 10, 92, 28, 71, 1, 80, 1, 70]
number_to_find = 1
for i,j in enumerate(numbers):
if j == number_to_find:
print i, "=>", j
# Output
>>> 5 => 1
>>> 7 => 1
If your numbers doesn't contains repeated numbers, you can use the following piece of code, as sugested by kojiro:
numbers = [24, 10, 92, 28, 71, 1, 80, 70]
number_to_find = 1
print numbers.index(number_to_find)
# Output
>>> 5
But if your code contains repeated chars, it'll show only the first ocurrence:
numbers = [24, 10, 92, 28, 71, 1, 80, 1, 70]
number_to_find = 1
print numbers.index(number_to_find)
# Output
>>> 5
while counter > 6:
If counter is greater than 6, it must be 7 or greater. If you're looping while counter > 7, you're indexing out of the range of the size of the list (which is indexed from 0 to 7).
global counter
Don't do this. You shouldn't use globals. There are good reasons
def my_loop():
...
my_loop()
You don't need recursion for this. This is quite simple with just a for loop (in fact, you can do it without that).
I'll post a few ways to solve this problem:
enumerate
def find_needle(needle, haystack):
for idx, item in enumerate(haystack):
if needle == item:
return idx
return None
index
def find_needle(needle, haystack):
return haystack.index(needle)
These two implementations don't do exactly the same thing - the first will return None if needle isn't found in haystack, where the second will throw a ValueError. I think the former is more forgiving, but it's up to you.
So there are many ways to do this, iteratively and recursively but to take the OP's code as is and what I think they were attempting.
Note: it is generally considered bad practice to use global variables, you should pass the list of numbers and the number to find to the function.
Note: your while loop is effectively implementing a for loop - for counter in range(len(numbers)): would provide the same result
numbers = [24, 10, 92, 28, 71, 1, 80, 70]
number_to_find = 1
def my_loop():
counter = 0
while counter < len(numbers):
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
counter = counter + 1
my_loop()
Output:
Counter not found in position 0
Counter not found in position 1
Counter not found in position 2
Counter not found in position 3
Counter not found in position 4
Number found at position 5
Counter not found in position 6
Counter not found in position 7
Doing the same thing with a for loop:
for counter in range(len(numbers)):
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
Would output the same.
However, perhaps a more idiomatic approach for Python would be to use enumerate:
for counter, number in enumerate(numbers):
if number == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
To find first occurence use numbers.index(x) where x is the number you are searching or for all of them indices = [idx for idx, number in enumerate(numbers) if elem_list == x]
For starters, I think you mean for your else block to correspond to the if. Right now it's associated with the while. Indent the else so it's aligned with the if, and then indent the three lines after the else to align with the print after the if:
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
counter = counter + 1
my_loop()
Once you fix that, your second problem will be that your program will exit immediately because your while condition evaluates to 0 > 6, which is false, so the if block will never even run. Minimally you'll want to change the > to <. At that point, your code will mostly work like you expect it to, but consider:
The application will go into an infinite loop once it finds the value it's looking for.
A for loop would be much nicer than a while with a counter.
You should really avoid using global variables if at all possible (it's very possible here).