How do I replace and update a string multiple times in Python? - string

I'm working on a quiz program and need some help. I'm trying to replace words one at a time, but Python isn't saving the previously replaced string. Here is a mini example of what I mean:
replacedQuiz=""
easyQuiz = """
You can change a string variable to an integer by typing (__1__)
in front of the variable. It also works vice versa, you can change an
integer
variable to a string by typing (__2__). This is important to remember before
you __3__ strings together, or else a TypeError will occur. While adding an
integer to a string, it is important to separate it using a __4__ (use the
symbol). \n"""
def replaceWord(replaced, quiz, numCount):
if numCount == 1:
replaced = quiz.replace("__1__", "int")
if numCount == 2:
replaced = replaced.replace("__2__", "str")
if numCount == 3:
replaced= replaced.replace("__3__", "concatenate")
if numCount == 4:
replaced= replaced.replace("__4__", ",")
print replaced
def easy():
QCount=1
print easyQuiz
while QCount < 5:
replaceWord(replacedQuiz, easyQuiz, QCount)
QCount += 1
print easy()
I thought that by making a String called replacedQuiz, it would save the first replacement and then I could continue replacing the words inside the quiz and updating it. Please help! I don't know where I'm going wrong

You seem to have made a slight mistake in the scope of your variable replacedQuiz (it'd certainly suggest that you check out some explanation of this topic). Basically, you are replacing replacedQuiz by its new value only within your current function. Your other functions only have access to the global value you defined earlier. There are several ways to fix this (e.g. the global keyword) but the standard way would be to return the new replacedQuiz from your function.
To do so, add the following line to the end of your replaceWord function:
return replacedQuiz
This tells Python to use this value at the line it was called at. You can then define a new value for replacedQuiz within easy by just defining it as the returned value:
replacedQuiz = replaceWord(replacedQuiz, easyQuiz, QCount)

Related

Remove & add split-list using dictionary python [duplicate]

I have the code below. I'm trying to remove two strings from lists predict strings and test strings if one of them has been found in the other. The issue is that I have to split up each of them and check if there is a "portion" of one string inside the other. If there is then I just say there is a match and then delete both strings from the list so they are no longer iterated over.
ValueError: list.remove(x): x not in list
I get the above error though and I am assuming this is because I can't delete the string from test_strings since it is being iterated over? Is there a way around this?
Thanks
for test_string in test_strings[:]:
for predict_string in predict_strings[:]:
split_string = predict_string.split('/')
for string in split_string:
if (split_string in test_string):
no_matches = no_matches + 1
# Found match so remove both
test_strings.remove(test_string)
predict_strings.remove(predict_string)
Example input:
test_strings = ['hello/there', 'what/is/up', 'yo/do/di/doodle', 'ding/dong/darn']
predict_strings =['hello/there/mister', 'interesting/what/that/is']
so I want there to be a match between hello/there and hello/there/mister and for them to be removed from the list when doing the next comparison.
After one iteration I expect it to be:
test_strings == ['what/is/up', 'yo/do/di/doodle', 'ding/dong/darn']
predict_strings == ['interesting/what/that/is']
After the second iteration I expect it to be:
test_strings == ['yo/do/di/doodle', 'ding/dong/darn']
predict_strings == []
You should never try to modify an iterable while you're iterating over it, which is still effectively what you're trying to do. Make a set to keep track of your matches, then remove those elements at the end.
Also, your line for string in split_string: isn't really doing anything. You're not using the variable string. Either remove that loop, or change your code so that you're using string.
You can use augmented assignment to increase the value of no_matches.
no_matches = 0
found_in_test = set()
found_in_predict = set()
for test_string in test_strings:
test_set = set(test_string.split("/"))
for predict_string in predict_strings:
split_strings = set(predict_string.split("/"))
if not split_strings.isdisjoint(test_set):
no_matches += 1
found_in_test.add(test_string)
found_in_predict.add(predict_string)
for element in found_in_test:
test_strings.remove(element)
for element in found_in_predict:
predict_strings.remove(element)
From your code it seems likely that two split_strings match the same test_string. The first time through the loop removes test_string, the second time tries to do so but can't, since it's already removed!
You can try breaking out of the inner for loop if it finds a match, or use any instead.
for test_string, predict_string in itertools.product(test_strings[:], predict_strings[:]):
if any(s in test_string for s in predict_string.split('/')):
no_matches += 1 # isn't this counter-intuitive?
test_strings.remove(test_string)
predict_strings.remove(predict_string)

Entering a word and then searching through and array of words to find the word

I am trying to create a program which checks to see if words entered (when run) are in an array. I would like to use a loop for this.
I have created a list of words and tried a for loop however the code is proving to be erroneous.
def Mylist():
Mylist= [Toyota,BMW,Pontiac,Cadillac,Ford,Opel]
Search=input("Enter a word")
Mylist[1]="Toyota"
for loop in range (1,6):
if Mylist[loop]==Search:
print("found")
break
I have repeated line 4 for the other car manufacturers.
TypeError: 'function' object does not support item assignment
First, here some recommendations to start:
Indentation in Python is IMPORTANT, be careful to have the right indentation. You must take special care when posting code here in SO so your code does not look like complete gibberish.
You should read Naming conventions. TL;DR we use snake_case for naming functions and variables.
If you are not using an IDE (such as PyCharm) to program, or something intelligent that shows the information on functions, you should always check out the documentation (it is beautiful).
Check out the difference between "Toyota" and Toyota. The first one has quotes, it is a string (i.e. chain of characters), it is a primitive type such as integer and boolean; the second is a token that is to be evaluated, it has to be defined before, such as variables, functions and classes.
Search in the docs if there is an in-built function that already does the job you want.
Check out return values in functions. Functions evaluate to None when you do not explicit a return value.
Now to your question. As some people pointed out, there is the in keyword that does exactly what you want.
CAR_BRANDS= ["Toyota", "BMW", "Pontiac", "Cadillac", "Ford","Opel"]
def check_car():
word = input("Enter a word: ")
if word in CAR_BRANDS:
print("found")
return True
print("not found")
return False
If you don't care about the print you can just do return word in CAR_BRANDS
If you actually want to challenge yourself to write the logic, you were right in choosing a for-loop to iterate over the list.
Index in Python starts from 0, and that range does not give you all the indexes to iterate over your list, you are missing the 0 index. Also, we don't like magic numbers, instead of hard-coding the length of your list of car brands, better compute the length!
for i in range(len(CAR_BRANDS)):
if CAR_BRANDS[i] == word:
print("found")
But even better you can directly iterate over the items in your list, no need to do the range, which will give you something like:
CAR_BRANDS= ["Toyota", "BMW", "Pontiac", "Cadillac", "Ford","Opel"]
def check_car():
word = input("Enter a word: ")
for brand in CAR_BRANDS:
if brand == word:
print("found")
return True
print("not found")
return False
If you have any more questions, do not hesitate! Happy coding.

Indexes and ranges in python

I have this code:
def main():
if (len(sys.argv) > 2) :
P=list()
f= open('Trace.txt' , 'w+')
Seed = int(sys.argv[1])
for i in range(2, len(sys.argv)):
P[i-2] = int(sys.argv[i])
for j in range(0, len(sys.argv)-1) :
Probability=P[j]
for Iteration in (K*j, K*(j+1)):
Instruction= generateInstruction(Seed, Probability)
f.write(Instruction)
f.close()
else:
print('Params Error')
if __name__ == "__main__":
main()
The idea is that I am passing some parameters through the command line. the first is seed and the rest I want to have them in a list that I am parsing later and doing treatments according to that parameter.
I keep receiving this error:
P[i-2] = int(sys.argv[i])
IndexError: list assignment index out of range
what am I doing wrong
PS: K, generateSegment() are defined in a previous part of the code.
The error you see is related to a list being indexed with an invalid index.
Specifically, the problem is that P is an empty list at the time is being called in that line so P[0] is indeed not accessible. Perhaps what you want is to actually add the element to the list, this can be achieved, for example, by replacing:
P[i-2] = int(sys.argv[i])
with:
P.append(int(sys.argv[i]))
Note also that argument parsing is typically achieved way more efficiently in Python by using the standard module argparse, rather than parsing sys.argv manually.
It looks like you might be referencing a list item that does not exist.
I haven't used Python in quite a while but I'm pretty sure that if you want to add a value to the end of a list you can use someList.append(foo)
The problem is that you are assigning a value to an index which does not yet exist.
You need to replace
P[i-2] = int(sys.argv[I])
with
P.append(int(sys.argv[i]))
Furthermore, len(sys.argv) will return the number of items in sys.argv however indexing starts at 0 so you need to change:
for i in range(2, len(sys.argv)):
with
for i in range(2, len(sys.argv)-1):
As you will run into a list index out of range error otherwise

Updating dictionary - Python

total=0
line=input()
line = line.upper()
names = {}
(tag,text) = parseLine(line) #initialize
while tag !="</PLAY>": #test
if tag =='<SPEAKER>':
if text not in names:
names.update({text})
I seem to get this far and then draw a blank.. This is what I'm trying to figure out. When I run it, I get:
ValueError: dictionary update sequence element #0 has length 8; 2 is required
Make an empty dictionary
Which I did.
(its keys will be the names of speakers and its values will be how many times s/he spoke)
Within the if statement that checks whether a tag is <SPEAKER>
If the speaker is not in the dictionary, add him to the dictionary with a value of 1
I'm pretty sure I did this right.
If he already is in the dictionary, increment his value
I'm not sure.
You are close, the big issue is on this line:
names.update({text})
You are trying to make a dictionary entry from a string using {text}, python is trying to be helpful and convert the iterable inside the curly brackets into a dictionary entry. Except the string is too long, 8 characters instead of two.
To add a new entry do this instead:
names.update({text:1})
This will set the initial value.
Now, it seems like this is homework, but you've put in a bit of effort already, so while I won't answer the question I'll give you some broad pointers.
Next step is checking if a value already exists in the dictionary. Python dictionaries have a get method that will retrieve a value from the dictionary based on the key. For example:
> names = {'romeo',1}
> print names.get('romeo')
1
But will return None if the key doesn't exist:
> names = {'romeo',1}
> print names.get('juliet')
None
But this takes an optional argument, that returns a different default value
> names = {'romeo',2}
> print names.get('juliet',1)
1
Also note that your loop as it stands will never end, as you only set tag once:
(tag,text) = parseLine(line) #initialize
while tag !="</PLAY>": #test
# you need to set tag in here
# and have an escape clause if you run out of file
The rest is left as an exercise for the reader...

Creating a function that creates two lists in Python 3

I am trying to create a function, getStocks, that gets from the user two lists, one containing the list of stock names and the second containing the list of stock prices. This should be done in a loop such that it keeps on getting a stock name and price until the user enters the string 'done' as a stock name. The function should return both lists. My main issues are figuring out what my parameters are, how to continuously take in the name and price, and what type of loop I should be using. I am very new to programming so any help would be appreciated. I believe I'm close but I am unsure where my errors are.
def getStocks(name,price):
stockNames = []
stockPrices = []
i = 0
name = str(input("What is the name of the stock?"))
price = int(input("what is the price of that stock?"))
while i < len(stockNames):
stockNames.append(name)
stockPrices.append(price)
i += 1
else:
if name = done
return stockNames
return stockPrices
Your question is a bit unclear but some things off the bat, you cant have two return lines, once you hit the first, it leaves the function. Instead you'do write something like
return (stockNames, stockPrices)
Secondly while loops dont have an else, so you'd actually set up your while loop, then setup an if statement at the beginning to check if the string is 'done', then act accordingly. Break will get you out of your last while loop, even though it looks like it's associated with the if. So something like this:
while i < len(stockNames):
if name.upper() == 'DONE':
break
else:
stockNames.append(name)
stockPrices.append(price)
i += 1
Also you have to use == (comparison) instead of = (assignment) when you check your name = done. And dont forget done is a string, so it needs to be in quotations, and I used .upper() to make the input all caps to cover if its lower case or uppercase.
If you can clear up your question a little bit, I can update this answer to include everything put together. I'm not quite understanding why you want to input a list and then also take user input, unless you're appending to that list, at which point you'd want to put the whole thing in a while loop maybe.
Update:
Based on your comment, you could do something like this and enclose the whole thing in a while loop. This takes the incoming two lists (assuming you made a master list somewhere) and sends them both into the getStocks function, where someone can keep appending to the pre-existing list, and then when they type done or DONE or DoNe (doesn't matter since you use .upper() to make the input capitalized) you break out of your while loop and return the updated lists:
def getStocks(name, price):
stockNames = name
stockPrices = price
while 1:
inputName = str(input("What is the name of the stock?"))
inputPrice = int(input("what is the price of that stock?"))
if name.upper() != 'DONE':
stockNames.append(inputName)
stockPrices.append(inputPrice)
else:
break
return (stockNames, stockPrices)
But really, depending on the rest of the structure, you might want to make a dictionary instead of having 2 separate lists, that way everything stays in key:value pairs, so instead of having to check index 0 on both and hoping they didn't get shifted by some rogue function, you'd have the key:value pair of "stock_x":48 always together.

Resources