'List' object has no attribute 'replace' - python

I'm trying to fill in the index location of my first_guess into my d array but im unsure what goes before the replace array function. need help lol
CODE PIC
I created a new variable called f, and im using the d array as the list varible before the replace function..
I have the location of the first_guess but im unsure how to input that into the replace function to replace the '_' in the d variable with the first_guess.

replace method is for strings, not lists. If you needed replace, you could convert d to a string using d = "".join(d), or use a list comprehension - f = list((y if i == first_guess else i) for i in d)
However you don't need replace for what you are describing. Replace finds all occurences of a string, and replaces it with a different string. You are trying to assign an element to an index, regardless of its current value.
You either need: f = d[:first_guess] + [y] + d[first_guess + 1:], meaning you create a new list that takes all elements from d until index first_guess, then y, and then all elements after index first_guess
or
f = d.copy()
f[first_guess] = y
Which means "f at index first_guess gets assigned y". The reason you need to copy d in the second solution is because list assignment just creates the reference to the list, it doesn't actually a create a new one. So if you didn't copy, changing f would change d.

The issue is that replace method is for strings and not lists. Plus it replaces all instances of a character ('_' in this case) by default and you can't pinpoint the index for which the replacement has to happen.
The solution is to use list indexing to reassign values at specific list index locations that match the index of the guessed letter in the hidden_word.
Below is the code that I have come up with. I'm also a newbie to python code, so I'm pretty sure that there will be a more concise code block for this. My code takes in the possibility of repeated guesses of the same letter and improper prompts and provides appropriate "counter measures" for the same.
Cheers!
hidden_word =input('Enter a word')
x = len(hidden_word)
d = ['_']*x
print(".".join(d))
responses = []
while d.count('_')!=0:
accepted_inputs=('y','n','yes','no')
run = input("Playing? (Y = 'Yes', N = 'No')")
if not run.lower() in accepted_inputs:
print('Wrong input')
continue
if run.lower() == 'y':
guess = input('Take a Guess')
if guess in responses:
print('Already guessed, try something else')
continue
else:
responses.append(guess)
for (n,m) in enumerate(hidden_word):
if (guess == m):
d[n]=guess
print(".".join(d))
else:
break
if d.count('_')==0:
print("Congratulations you guessed it!")

Related

Building a list by input() python without setting a number of elements

i study python on my own in the middle of an ocean with limited access to internet.
I'm thinking of a way to make a list by input() without setting a number of elements in the beginning.
So far i end up with this:
list = []
value = None
while value != '':
value = input()
list.append(value)
if value == '':
del list[-1]
break
print(list)
As i can see, code works fine, i can create a list by input(), but it seems ugly to me.
I found the way 'With handling exception', but it works only for string or int.
Thank you!
Here is a way I would write it:
lst = list()
while True:
value = input()
if value == "":
break
lst.append(value)
First, use while True to loop forever, with an intention of breaking when certain input is encountered. When value is read, check if it is empty. If so, break. Otherwise, append value to lst and continue with the loop.
By the way, I renamed list to lst to avoid variable shadowing.
Can be written more compactly using the walrus operator (assignment with value):
li = list()
while (val := input()):
li.append(val)
This saves the input into val and simultaneously evaluates whether it's empty or not, breaking the loop in the former case. It uses the fact that empty strings evaluate to False.
So, assignment expressions were added for this very sort of pattern:
data = []
while (value:= input()):
data.append(value)
Note the assignment expression "walrus operator" := is only available in Python >= 3.8
Otherwise, you'd generally do something like:
data = []
value = input()
while value:
data.append(value)
value = input()
well if you want users to input the element multiple times then the above answers are good.
But just say you want an input of elements using a specific separator(space or comma etc) you can do this in one line.
eg. if you were to take input using a space as separator,
l = [x for x in input().split()] would build your list and
if you were to take input and keep , as a separator you could do something like
l = [x for x in input().split(sep=",")].

reverse backslash on string input

i have to write a code for a class where i have to define a function, and the parameters come from an input(). the input is always going to be a string with numbers and letters following each other, in this form :""5 2 S 2 333 A" ". depending on the letter following the 2 numbers, i have to do use a certain function on the two previous numbers. for this i go through the string input and add each element to a list so it is easier to work with them. my issue is, that the first and last element of the last always start/end with a reverse backslash, making it impossible to int() the numbers, and i dont why and how to get rid of them. here is my code, if you know an easier way i would appreciate it but i mostly want to know where the backslashes come from...
def addition(a,b):
return a + b
def soustraction(a,b):
return a - b
def multiplication(a,b):
return a * b
if __name__ == '__main__':
c = input() #here comes the string input
ma_liste = [] #the list where i want to add the elements of my string
for i in range(0, len(c)): #checking each element of the string
if i == 0:
for j in range(len(c)):
if " " in c[i:j+2]:
ma_liste.append(c[i:j+1])
break
else:
for j in range(i,len(c)): #check if there is a space to know where the number ends
if c[i:j+1] == c[i-1:j+2].strip():
ma_liste.append(c[i:j+1])
break
for e in range(len(ma_liste)): #going through the elements of my list
if ma_liste[e].isdigit():
int(ma_liste[e])
if ma_liste[e].isalpha():
if ma_liste[e] == "S":
soustraction(int(ma_liste[e-2]),int(ma_liste[e-1]))
if ma_liste[e] == "A":
addition(int(ma_liste[e-2]),int(ma_liste[e-1]))
if ma_liste[e] == "M":
multiplication(int(ma_liste[e-2]),int(ma_liste[e-1]))
Welcome to SO. Seems like the issue here is that the end of the line '\n' gets appended when you read the data as it is directly. May be convert the whole ndarray to using numpy.asarray dtype=int. This will solve your problem. Hope it helps. :)
import numpy as np
a = ['1','2','3\n']
print(a)
b = np.asarray(a,dtype=np.int)
print(b)
input: ['1', '2', '3\n']
output: [1 2 3]

How to skip empty lists when iterating over lists within a list?

Take the following code as an example:
a = [['James Dean'],['Marlon Brando'],[],[],['Frank Sinatra']]
n = 0
for i in a:
print a[n][0]
n = n + 1
I seem to be getting an error with the index value:
IndexError: list index out of range
How do I skip over the empty lists within the list named a?
Simple:
for i in a:
if i:
print i[0]
This answer works because when you convert a list (like i) to a boolean in an if statement like I've done here, it evaluates whether the list is not empty, which is what you want.
You can check if the list is empty or not, empty lists have False value in boolean context -
for i in a:
if i:
print a[n][0]
n = n + 1
Also, instead of using n separately, you can use the enumerate function , which returns the current element as well as the index -
for n, i in enumerate(a):
if i:
print a[n][0] # though you could just do - print i[0]
You could either make a test, or catch the exception.
# Test
for i in a:
if a[n]:
print a[n][0]
n = n + 1
# Exception
for i in a:
try:
print a[n][0]
except IndexError:
pass
finally:
n = n + 1
You could even use the condensed print "\n".join(e[0] for e in a if e) but it's quite less readable.
Btw I'd suggest using using for i, element in enumerate(a) rather than incrementing manually n
Reading your code, I assume you try to get the first element of the inner list for every non empty entry in the list, and print that. I like this syntax:
a = [['James Dean'],['Marlon Brando'],[],[],['Frank Sinatra']]
# this filter is lazy, so even if your list is very big, it will only process it as needed (printed in this case)
non_empty_a = (x[0] for x in a if x)
for actor in non_empty_a : print (actor)
As mentioned by other answers, this works because an empty list is converted to False in an if-expression

Python number to word converter needs a space detector

I have been working on a sort of encryption tool in python. This bit of code is for the decryption feature.
The point is to take the given numbers and insert them into a list from where they will be divided by the given keys.
My idea for code is below but I keep getting the out of list index range whenever I try it out. Any suggestions? Keep in mind I'm a beginner:
need = []
detr = raw_input('What would you like decrypted?')
count = 0
for d in detr:
if (d == '.' or d == '!') or (d.isalpha() or d== " "):
count +=1
else:
need[count].append(d)
The problem is you are attempting to overwrite list values that don't exist.
list.append(item) adds item to the end of list. list[index] = item inserts item into list at position index.
list = [0,0,0]
list.append(0) # = [0,0,0,0]
list[0] = 1 # [1,0,0,0]
list[99] = 1 # ERROR: out of list index range
You should get rid of the count variable entirely. You could append None in the case of d==' ' etc. or just ignore them.
The way I understood your description you want to extract the numbers in a string and append them to a list using a for-loop to iterate over each character.
I think it would be easier doing it with regular expressions (something like r'([\d]+)').
But the way joconner said: "get rid of the count variable":
need = []
detr = input('What would you like decrypted?\n')
i = iter(detr) # get an iterator
# iterate over the input-string
for d in i:
numberstr = ""
try:
# as long as there are digits
while d.isdigit():
# append them to a cache-string
numberstr+= d
d = next(i)
except StopIteration:
# occurs when there are no more characters in detr
pass
if numberstr != "":
# convert the cache-string to an int
# and append the int to the need-array
need.append( int(numberstr) )
# print the need-array to see what is inside
print(need)

Index error:list assignment index out of range

I want to:
Take two inputs as integers separated by a space (but in string form).
Club them using A + B.
Convert this A + B to integer using int().
Store this integer value in list C.
My code:
C = list()
for a in range(0, 4):
A, B = input().split()
C[a] = int(A + B)
but it shows:
IndexError: list assignment index out of range
I am unable understand this problem. How is a is going out of the range (it must be starting from 0 ending at 3)?
Why it is showing this error?
Why your error is occurring:
You can only reference an index of a list if it already exists. On the last line of every iteration you are referring to an index that is yet to be created, so for example on the first iteration you are trying to change the index 0, which does not exist as the list is empty at that time. The same occurs for every iteration.
The correct way to add an item to a list is this:
C.append(int(A + B))
Or you could solve a hella lot of lines with an ultra-pythonic list comprehension. This is built on the fact you added to the list in a loop, but this simplifies it as you do not need to assign things explicitly:
C = [sum(int(item) for item in input("Enter two space-separated numbers: ").split()) for i in range(4)]
The above would go in place of all of the code that you posted in your question.
The correct way would be to append the element to your list like this:
C.append(int(A+B))
And don't worry about the indices
Here's a far more pythonic way of writing your code:
c = []
for _ in range(4): # defaults to starting at 0
c.append(sum(int(i) for i in input("Enter two space-separated numbers").split()))
Or a nice little one-liner:
c = [sum(int(i) for i in input("Enter two space-separated numbers").split()) for _ in range(4)]

Categories