I have the following list:
Words = ['This','is','a','list','and','NM,']
Note: Words[5] >>> NM, (with a comma(,))
New_List = []
for word in Words:
if word[:2] =="NM":
Words.insert((Words.index("NM")),input("Input a " + ac_to_word("NM") + ": "))
Words.remove("NM")
Whenever I try to run this I get:
Words.insert((Words.index("NM")),input("Input a " + ac_to_word("NM") + ": "))
ValueError: 'NM' is not in list
Yet "NM" is the in index 5. What's going on here? I am asking for word[:2] not the whole word.
I tried figuring out the problem,but no one was around to look at my code, and give me feedback, so I though maybe some people out there might be able to help. If you see a mistake, please show me where. Any help is appreciated!
Several problems:
You're trying to access a string 'NM' in the list that has no such item.
You're modifying the list as you iterate over it. Don't do this! It will have unexpected consequences.
An easier way here would probably be to iterate over the list indices instead of the items:
Words = ['This','is','a','list','and','NM,']
for i in xrange(len(Words)):
if Words[i].startswith('NM'):
Words[i] = input("Input a " + ac_to_word("NM") + ": ")
Notice that I'm simply replacing the NM... items with the result of input(). This is more efficient than inserting and removing elements.
The error is coming from here:
Words.index("NM")
'NM' is not in your list of strings.
Doing insert and remove operations on a sequence while you iterate over it is a bad, bad idea. It is a surefire way to skip an item, or to double-operate on an item. Also, you should not be doing linear searches with index since a) it is slow and b) what happens if you have duplicates?
Just use enumerate:
for i,word in enumerate(words):
if word[:2] == 'NM':
words[i] = input('replace NM with something: ')
Related
This should be an easy one but I have simply not come to a solution.
This is the exercise:
Start with 4 words “comfortable”, “round”, “support”, “machinery”, return a list of all possible 2 word combinations.
Example: ["comfortable round", "comfortable support", "comfortable machinery", ...]
I have started coding a loop that would go through every element, starting with the element at index[0] :
words = ["comfortable, ", 'round, ', 'support, ', 'machinery, ']
index_zero= words[0]
for i in words:
words = index_zero + i
words_one = index_one + i
print(words)
>>> Output=
comfortable, comfortable,
comfortable, round,
comfortable, support,
comfortable, machinery
The issue is when I want to start iterating from the 2nd element ('round'). I have tried operating the indexes (index[0] + 1) but of course, it won't return anything as the elements are strings.
I know a conversion from string to indexes needs to take place, but I'm not sure how.
I have also tried defining a function, but it will return None
word_list = ["comfortable, ", 'round, ', 'support, ', 'machinery, ']
index_change = word_list[0]+ 1
def word_variations(set_of_words):
for i in set_of_words:
set_of_words = set_of_words[0] + i
set_of_words = word_variations(word_list)
print(set_of_words)
I think this would do what you're looking for:
def word_variations(word_list):
combinations = []
for first_word in word_list:
for second_word in word_list:
if first_word != second_word:
combinations.append(f'{first_word}, {second_word}')
return combinations
word_list = ["comfortable", "round", "support", "machinery"]
print(word_variations(word_list))
Explanation:
You need to include a return statement at the end of the function to return a value. In my example function word_variations(), I first define an empty list called combinations. This will store each combination we compute. Then I iterate through all the words in the input word_list, create another inner loop to iterate through all words again, and if the first_word does not equal the second_word append the combination to my combinations list. Once all loops are complete, return the finished list from the function.
If I slightly change the code to print each of the results on a new line:
def word_variations(word_list):
combinations = []
for first_word in word_list:
for second_word in word_list:
if first_word != second_word:
combinations.append(f'{first_word}, {second_word}')
return combinations
word_list = ["comfortable", "round", "support", "machinery"]
for combo in word_variations(word_list):
print(combo)
the output is:
comfortable, round
comfortable, support
comfortable, machinery
round, comfortable
round, support
round, machinery
support, comfortable
support, round
support, machinery
machinery, comfortable
machinery, round
machinery, support
If you want to work with indexes in a Python loop like that, you should use either enumerate or iterate over the length of the list. The following examples will start the loop at the second element.
Example getting both index and the word at once with enumerate:
for i, word in enumerate(set_of_words[1:]):
Example using only indexes:
for i in range(1, len(set_of_words)):
Note: set_of_words[1:] above is a slice that returns the list starting at the second element.
You can also use itertools.permutations() like this
from itertools import permutations
lst = ['comfortable', 'round', 'support', 'machinery']
for i in list(permutations(lst, 2)):
print(i)
Beginner here. I'm having problems with this task: accum("hello") should return "H-Ee-Lll-Llll-Ooooo". But what I get with my code is "H-Ee-Lll- Lll -Ooooo". It doesn't work for double characters. Is this because the iteration variable in "for i in s" "skips" over double "i's" or something? And do you have an idea how I can fix this? I'm not striving for elegant code or something, my goal atm is to try and make easily readable lines for myself :)
Thank you!
(Sorry if this is something basic, I didn't really know what to search for!)
def accum(s):
s_list = []
s = [ele for ele in s]
for i in s:
sum_ind = ((s.index(i)) + 1) * i
s_list.append(sum_ind)
s_list = [e.capitalize() for e in s_list]
s_list = '-'.join(s_list)
return s_list
Here's a way to do:
def accum(stri):
p = []
for i, s in enumerate(stri, 1):
p.append((s*i).capitalize())
return '-'.join(p)
accum('hello')
'H-Ee-Lll-Llll-Ooooo'
Take a quick read about: enumerate
I think you could solve this easily with enumerate:
def accum(s):
r = []
for i, letter in enumerate(s):
r.append(letter.upper() + (letter*i).lower())
return '-'.join(r)
Here is one way:
def accum(s):
return "-".join( (c*i).capitalize() for i,c in enumerate(s,1) )
yields:
'H-Ee-Lll-Llll-Ooooo'
As mentioned in many comments, we can give a short explanation of working of enumerate here.
As per your requirement, given a letter from a string, you find its index (position). Then you first make the caps of letter and glue it with index-times small letters.
So you need a counter which keeps track of the position of letter, so we can do something like this (A DUMMY, SLOW EXAMPLE):
def accum(word):
ans = ""
for index in range(len(word)):
letter = word[index]
ans += letter.upper() + index*letter + "-"
else:
word = word[:-1] #Remove trailing '-'
return word
BUT THIS FUNCTION IS EXTREMELY SLOW. BECAUSE IT USES SIMPLE STRING ADDITION AND NOT OTHER PROPER METHOD.
That's why people ask you to use enumerate. In short it keeps track of your indices.
for index, name in enumerate(["John", "Lex", "Vui"]):
print(name, "is found at", index)
That's it !
{Im not writing the answer you wanted, as almost everyone provided the best answer, they could, my aim was to explain you the use of enumerate and other slow methods for your problem}
This is my code, but it doesn't work. It should read text from the console, split it into words and distribute them into 3 lists and use separators between them.
words = list(map(str, input().split(" ")))
lowercase_words = []
uppercase_words = []
mixedcase_words = []
def split_symbols(list):
from operator import methodcaller
list = words
map(methodcaller(str,"split"," ",",",":",";",".","!","( )","","'","\\","/","[ ]","space"))
return list
for word in words:
if words[word] == word.lower():
words[word] = lowercase_words
elif words[word] == word.upper():
words[word] = uppercase_words
else:
words[word] = mixedcase_words
print(f"Lower case: {split_symbols(lowercase_words)}")
print(f"Upper case: {split_symbols(uppercase_words)}")
print(f"Mixed case: {split_symbols(mixedcase_words)}")
There are several issues in your code.
1) words is a list and word is string. And you are trying to access the list with the index as string which will throw an error. You must use integer for indexing a list. In this case, you don't even need indexes.
2) To check lower or upper case you can just do, word == word.lower() or word == word.upper(). Or another approach would be to use islower() or isupper() function which return a boolean.
3) You are trying to assign an empty list to that element of list. What you want is to append the word to that particular list. You want something like lowercase_words.append(word). Same for uppercase and mixedcase
So, to fix this two issues you can write the code like this -
for word in words:
if word == word.lower(): # same as word.islower()
lowercase_words.append(word)
elif word == word.upper(): # same as word.isupper()
uppercase_words.append(word)
else:
mixedcase_words.append(word)
My advice would be to refrain from naming variable things like list. Also, in split_words() you are assigning list to words. I think you meant it other way around.
Now I am not sure about the "use separators between them" part of the question. But the line map(methodcaller(str,"split"," ",",",":",";",".","!","( )","","'","\\","/","[ ]","space")) is definitely wrong. map() takes a function and an iterable. In your code the iterable part is absent and I think this where the input param list fits in. So, it may be something like -
map(methodcaller("split"," "), list)
But then again I am not sure what are you trying to achieve with that many seperator
I´ve searched for other "string index out of range" cases, but they were not useful for me, so I wanted to search for help here.
The program has to do this: "Write a function kth_word(s, k) that given a string s and an integer k≥ 1 returns the kth word in string s. If s has less than k words it returns the empty string. We assume all characters of s are letters and spaces. Warning: do not use the split string method."
Here is my code:
def kth_word(s, k):
new =""
word_count = 0
for i in range(0, len(s)):
if s[i] == " " and s[i+1] != " ":
word_count+=1
#try to find how many characters to print until the space
if word_count == k-1:
while i!= " " and i<=len(s): #if it is changed to i<len(s), the output is strange and wrong
new+=s[i]
i=i+1
print(new) #check how new is doing, normally works good
return new
print(kth_word('Alea iacta est', 2))
(I tried my best to implement the code in a right way, but i do not know how)
And depending on the place where you live return new it gives or an error or just an empty answer
You iterate from 0 to len(s)-1 in your first for loop, but you're addressing i+1 which, on the last iteration, is len(s).
s[len(s)] is an IndexError -- it is out of bounds.
Additionally your while loop is off-by-one.
while i!= " " and i<=len(s):
# do something referencing s[i]
Your first condition makes no sense (i is a number, how could it be " "?) and your second introduces the same off-by-one error as above, where i is maximally len(s) and s[len(s)] is an error.
Your logic is a bit off here, too, since you're wrapping this inside the for loop which is already referencing i. This appears to be a takewhile loop, but isn't really doing that.
Warning: do not use the split string method.
So groupby / islice from itertools should work:
from itertools import groupby, islice
def kth_word(s, k):
g = (j for i, j in groupby(s, key=lambda x: x==' ') if not i)
return ''.join(next(islice(g, k-1, k), ''))
words = 'Alea iacta est'
res = kth_word(words, 2) # 'est'
We handle StopIteration errors by setting the optional parameter in next to ''.
You're not allowed to use str.split. If you could, the answer would just be:
def kth_word(s, k):
return s.split()[k]
But if you could write a function that does the same thing str.split does, you could call that instead. And that would certainly show that you understand everything the assignment was testing for—how to loop over strings, and do character-by-character operations, and so on.
You can write a version with only the features of Python usually taught in the first week:
def split(s):
words = []
current = ''
for ch in s:
if ch.isspace():
if current:
words.append(current)
current = ''
else:
current += ch
if current:
words.append(current)
return words
If you know additional Python features, you can improve it in a few ways:
Build current as a list instead of a str and ''.join it.
Change those append calls to yield so it splits the string lazily (even better than str.split).
Use str.find or str.index or re.search to find the next space instead of searching character by character.
Abstract out the space-finding part into a general-purpose generator—or, once you realize what you want, find that function in itertools.
Add all of the features we're missing from str.split, like the ability to pass a custom delimiter instead of breaking on any whitespace.
But I think even the basic version—assuming you understand it and can explain how it works—ought to be enough to get an A on the assignment.
And, more importantly, you're practicing the best way to solve problems: reduce them to simpler problems. split is actually easier to write than kth_word, but once you write split, kth_word becomes trivial.
You actually have at least five problems here, and you need to fix all of them.
First, as pointed out by Adam Smith, this is wrong:
for i in range(0, len(s)):
if s[i] == " " and s[i+1] != " ":
This loops with i over all the values up to but not including len(s), which is good, but then, if s[i] is a space, it tries to access s[i+1]. So, if your string ended with a space, you would get an IndexError here.
Second, as ggorlen pointed out in a comment, this is wrong:
while i!= " " and i<=len(s):
new+=s[i[]
When i == len(s), you're going to try to access s[i], which will be an IndexError. In fact, this is the IndexError you're seeing in your example.
You seem to realize that's a problem, but refuse to fix it, based on this comment:
#if it is changed to i<len(s), the output is strange and wrong
Yes, the output is strange and wrong, but that's because fixing this bug means that, instead of an IndexError, you hit the other bugs in your code. It's not causing those bugs.
Next, you need to return new right after doing the inner loop, rather than after the outer loop. Otherwise, you add all of the remaining words rather than just the first one, and you add them over and over, once per character, instead of just adding them once.
You may have been expecting that doing that i=i+1 would affect the loop variable and skip over the rest of the word, but (a) it won't; the next time through the for it just reassigns i to the next value, and (b) that wouldn't help anyway, because you're only advancing i to the next space, not to the end of the string.
Also, you're counting words at the space, but then you're iterating from that space until the next one. Which means (except for the first word) you're going to include that space as part of the word. So, you need to do an i += 1 before the while loop.
Although it would probably be a lot more readable to not try to reuse the same variable i, and also to use for instead of while.
Also, your inner loop should be checking s[i] != " ", not i!=" ". Obviously the index, being a number, will never equal a space character.
Without the previous fix, this would mean you output iacta est
with an extra space before it—but with the previous fix, it means you output nothing instead of iacta.
Once you fix all of these problems, your code works:
def kth_word(s, k):
word_count = 0
for i in range(0, len(s) - 1):
if s[i] == " " and s[i+1] != " ":
word_count+=1
#try to find how many characters to print until the space
if word_count == k-1:
new =""
j = i+1
while j < len(s) and s[j] != " ":
new+=s[j]
j = j+1
print(new) #check how new is doing, normally works good
return new
Well, you still have a problem with the first word, but I'll leave it to you to find and fix that one.
Your use of the variable 'i' in both the for loop and the while loop was causing problems. using a new variable, 'n', for the while loop and changing the condition to n < len(s) fixes the problem. Also, some other parts of your code required changing because either they were pointless or not compatible with more than 2 words. Here is the fully changed code. It is explained further down:
def kth_word(s, k):
new = ""
word_count = 0
n = 0
for i in range(0, len(s) - 1):
if s[i] == " " and s[i + 1] != " ":
word_count += 1
#try to find how many characters to print until the space
if word_count < k:
while n < len(s): #if it is changed to i<len(s), the output is strange and wrong
new+=s[n]
n += 1
print(new) #check how new is doing, normally works good
return new
print(kth_word('Alea iacta est', 2))
Explanation:
As said in Adam Smith's answer, 'i' is a number and will never be equal to ' '. That part of the code was removed because it is always true.
I have changed i = i + 1 to i += 1. It won't make much difference here, but this will help you later when you use longer variable names. It can also be used to append text to strings.
I have also declared 'n' for later use and changed for i in range(0, len(s)): to for i in range(0, len(s) - 1): so that the for loop can't go out of range either.
if word_count == k-1: was changed to if word_count < k: for compatibility for more words, because the former code only went to the while loop when it was up to the second-last word.
And finally, spaces were added for better readability (This will also help you later).
My brain cannot comprehend why this isn't working. I'm not very experienced and just trying to practice loops.
I'm trying to create a function that takes a string (currently one word) and capitalizes letters at random. With this code python throws a TypeError: list indices must be integers or slices, not strings
Here's what I have:
import random
list = []
def hippycase(string):
for letter in string:
list.append(letter)
for index in list:
if random.randint(1,2) == 1:
list[index] = list[index].upper()
else:
list[index] = list[index].lower()
return list
print(hippycase("pineapple"))
Any ideas or tips? Thanks
EDIT: Since this has been marked as a duplicate as someone thinks is at the following link, I'll try and clear up what is different:
Accessing the index in Python 'for' loops
I'm not trying to actively seek the index, I'm just practicing for loops which coincidentally goes through the index of the iterable sequentially. I also think if a fellow noob coder is searching this might be more helpful.
Here's a slightly improved version of your code
def hippycase(string):
charlist = []
for char in string:
if random.randint(1,2) == 1:
charlist.append(char.upper())
else:
charlist.append(char.lower())
return charlist
Notice that in this version we're looking only at the characters in your string, we don't care about the indices - this helps to reduce confusion.
If I were writing this to actually "hippycase" a string I would probably return "".join(charlist), so the calling function would get back a string (which is what they probably expect)
Also, it is bad practice to overwrite the list reserved word.
The variable "index" that you are using is a letter from the string, because you are iterating over it. To fix this error, use the range() function, which will allow you to access each element in the list by index:
list = []
def hippycase(string):
for letter in string:
list.append(letter)
for index in range(len(list)): #here, we are accessing the elements by index
if random.randint(1,2) == 1:
list[index] = list[index].upper()
else:
list[index] = list[index].lower()
return list
print(hippycase("pineapple"))
Another way is simple list comprehension:
the_string = "pineapple"
print ''.join([i.upper() if random.randint(1, 2) == 1 else i for i in the_string])