how to delete and append in a list python - python

This is my code
k = []
dot = input('length:')
a, b = input('Enter:')
for i in range(0,dot):
k.append('.')
for i in range(a, b+1):
k[i].append('x')
print k
when i try to run this the output will be like,
length:9
Enter:3, 4
Traceback (most recent call last):
File "light_switch.py", line 8, in <module>
k[i].append('x')
AttributeError: 'str' object has no attribute 'append'
i want to insert a 'x' in the the place of '.'. so how do i do it.

If you want to replace the '.' in the second range with 'x', just do:
for i in range(a, b+1):
k[i] = 'x'
The error is because when you index to k[i] you get the str you put there, only k is a list, but the values are str. str, being immutable, lacks an append method (and since you say you want to replace, not concatenate, you wouldn't want an append-like operation anyway). If you wanted append-like behavior to each '.', you'd change k[i].append('x') to k[i] += 'x' (which is logically constructing a new concatenated str and assigning it back, rather than mutating in place), or to add a whole bunch of xs to the end of the list, you'd just do k.append('x').
Note: If a < 0 or b+1 > dot, this will raise an IndexError; the former is unfixable, the latter could be handled in a kludgy way by simply making the first for loop run over range(max(dot, b+1)) instead of range(dot).

To replace the dot with x you can try this code:
k = []
dot = input('length:')
a, b = input('Enter:')
for i in range(0,dot):
k.append('.')
for i in range(a, b+1):
k[i] = 'x'
print k
You already have a '.' at the location you are trying to add x so you just need to assign x instead of '.'. Location you are trying to access using a[j].append('x') is not a list and you are trying yo append x to it. So it is giving error.

Related

Bad Function Python

I am new to Python and learning by myself.
This is my first post here, I appreciate any help that you can give me.
I have been trying to find the min value and the index on a list with a function.
This is the code that I wrote:
def findMin (L,startIndx):
m = L[startIndx]
index = startIndx
for i in range (startIndx,len(L)):
x = L[i]
if i < m:
i = index
m = x
else:
pass
return (m,index)
a,b = findMin([8,2,11,0,5])
print (a,b)
This is the error that I get:
**TypeError Traceback (most recent call last)
<ipython-input-33-9713029875a6> in <module>
----> 1 a,b = findMin([8,2,11,0,5])
2 print (a,b)
TypeError: findMin() missing 1 required positional argument: 'startIndx'**
I truly have no idea what is the problem with it, I appreciate any help,
The problem that you ran into is that you only passed one argument (L) and not the second one (startIndx) and you have some logic errors in your code as mentioned by other answers.
This is a much shorter way of writing your function using some built-in functions that isn't that error-prone.
Very compact form:
def findMin(L,startIndx=0):
m = min(L[startIndx:])
return (m, L.index(m))
Here is the more spaced out version of that function with some explenations.
#Notice that startIndx is a OPTIONAL ARGUMENT. This means if we don't pass anything to it, it will be defined to be 0
def findMin(L,startIndx=0):
#The searchspace is defined by SLICING the list using list[from:upto]
searchspace = L[startIndx:]
#Using the built-in min() function we find the smallest value in the list
m = min(searchspace)
#Then we use the built-in list.index(value) function to find the index of the smallest element
#Quick reminder: The first value in a list has the index 0
index = L.index(m)
#Finally we return the needed values
return (m, index)
This is how the function is called with startIndx:
test_list = [5,0,9,4,11]
test_index = 3
a,b = findMin(test_list, test_index)
print(a,b)
#--> 4, 3
When you call the function without the startIndx argument it searches through the entire list, because the optional argument startIndx is set to 0.
test_list = [5,0,9,4,11]
a,b = finMin(test_list)
print(a,b)
#--> 0, 2
So I can see a few errors in your algorithm.
First error:
findMin() missing 1 required positional argument: 'startIndx'
This error is due to the fact that findMin is a function that takes two arguments. First argument is the array you want to find the minimum of ([8,2,11,0,5] in your example). The second one is the startIndex. It is the index which you want to start at while searching for the min. You can add this index to your function call or add a default value in your funtion declaration.
Second error:
line 6: if i < m:
This is not what you want to do. Here you are comparing i (which is the current index of your for loop) and m which is the minimum value so far. You want to compare x and m like this:
if x < m
Third and last error:
i = index
This is wrong. You want to swap these two variables and assign i to index like this:
index = i
Here is the final correct code:
def findMin (L,startIndx):
m = L[startIndx]
index = startIndx
for i in range (startIndx+1,len(L)):
x = L[i]
if x < m:
index = i
m = x
else:
pass
return (m, index)
a,b = findMin([8,2,11,3,1], 0)
print (a,b)
Call with two parameters; findMin([8,2,11,0,5]) passes a single list. Perhaps findMin([8,2,11,0,5], 0).
Indentation appears to be incorrect, and this is critical in Python. All lines from "m =" to "return" must be indented one more level.
Variable naming could be improved; part of the confusion is likely from names like "m", "x", etc. What does m mean, vs. for example max_val?
Indexing seems confused; first you set index = startIndx then use for i. Delete the index = and use for index in range (startIndx + 1, len(L)) (you already have L[startIndx]).
What is the desired behavior and return value if startIndx is > len(L)?
Why comparing i to m?
Optimization: don't need the else: pass. It means "otherwise, do nothing" which does not need to be explicit.
findMin has two parameters, but you only pass it one argument. You have two choices:
Pass the argument that findMin requires.
a,b = findMin([8,2,11,0,5], 0)
Remove the startIndx parameter and use 0 instead:
def findMin (L):
index = 0
m = L[index]
for i in range (len(L)):
x = L[i]
if x < m:
index = i
m = x
else:
pass
return (m,index)
def findMin (L,startIndx): this function will expect 2 arguments L and startIndx. So you'll have to pass 2 arguments as well. But you are passing only 1 argument findMin([8,2,11,0,5]). [8,2,11,0,5] as a list is one argument passed to L, then missing one for startIndx which results in error.
startIndx seems unnecessary as well since all the elements needs to be traverse.
def findMin(L):
m = L[0]
index = 0
for i in range (1,len(L)):
if L[i]<m:
m=L[i]
index=i
return (m,index)
a,b = findMin([8,2,11,0,5])
print (a,b)

Python ForLoop Input

Basically I have to create a function where I input 2 arguments:
the first one being a letter (i.e 'i')
the second one being a list (i.e ['trees', 'iron', 'cars', 'indian'])
my function should return every item in the list that begins with the same letter in my first argument.
so for I have:
def match_first_letter(G, F):
for i in F:
if i.F[0] == G:
return F
where G is the first letter and F is the list
I keep getting:
AttributeError: 'str' object has no attribute 'L'
Is there anything specific that I am doing wrong?
First look at the line:
for i in F:
Here, you can access one element of F through i at a time.
So, you should use i[0] (first digit of i) rather than i.F[0].
Secondly,
You are returning the list, not the matched value.
If you correct it, still you only have the first match even if you have multiple match.
That's because, you are returning immediately after first match.
You can achieve your expected output with a list comprehension.
def match_first_letter(G, F):
return [i for i in F if i[0]==G]
Inside the loop you can say:
if i.startswith(G):
yield i
You can call this function as:
matches = list(match_first_letter(F, G))
First of all, you might do better to name variables sensibly. Instead of G and F, how about letter and strings? Your code is thus this:
def match_first_letter(letter, strings):
for current_string in strings:
if current_string.strings[0] == letter:
return strings
In this case, the error that you have been seeing will instead say AttributeError: 'str' object has no attribute 'strings'. Note that this matches the current_string.strings command.
current_string[0] is what you actually want to be testing against matching letter, as that is the first letter of the string current_string.
Finally, you're currently returning the list. Instead, you should add current_string to a list to be returned.
def match_first_letter(letter, strings):
matched_strings = []
for current_string in strings:
if current_string[0] == letter:
matched_strings.append(current_string)
return matched_strings
Python actually has something called list comprehensions which can do this kind of thing much more easily.
def match_first_letter(letter, strings):
return [string_x for string_x in strings if string_x[0] == letter]
I'd recommend reading up on list comprehensions at the above link.
Since you're already saying for i in F: you can just say if i[0] == G. That is, access the zeroth element of i.
I believe you're trying to return iron and indian in the above example. See if something like this works for you.
arg1 = 'i'
arg2 = ['trees', 'iron', 'cars', 'indian']
def match_first_letter(G, F):
for i in F:
if i[0] == G:
print(i)
match_first_letter(arg1, arg2)

zip function to store multiple outputs for a return statement

def somefunction():
outputs = []
a = 0
while a < 100:
if a%2 == 0:
b = 2*a + 1
outputs.append(list(zip(a,b)))
a += 1
return outputs
The above code is not what i'm using exactly but produces the same error, why does the above code return:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
TypeError: zip argument #1 must support iteration
Is this a particularly efficient way of returning all the items within a function as one? If not, what is a better method?
It returns that error because of its exact error message; that is, the zip arguments must support iteration. You just have two numbers that you are trying to "store together". In that case, I'm assuming what you are looking for is the tuple data type. Either that or "put them together" with the list data type you already have. The zip is entirely unnecessary. I would suggest reading more about Python's built-in types.
Just get a list of tuples!! (or list if you prefer, but since you can't change tuples and you want to return all the outputs, tuples make more sense)
def somefunction():
outputs = []
a = 0
while a < 100:
if a%2 == 0:
b = 2*a + 1
tup = (a,b)
outputs.append(tup)
a += 1
return outputs
There is no need to use zip here, zip is for joining two lists together, you only have two integers so you can store them in a tuple and then append the tuple to outputs
when zip would work for this
Zip would work if you stored all as in a_list and all bs in b_list. Then you could do:
outputs.append(zip(a_list,b_list))
this is unnecessary because you can just append a and b together in a tuple to output just like my example. But that is how it would be done.
You can also use list comprehension in this case:
def f():
return [(x, 2*x + 1) for x in range(100) if x%2 == 0]

Function passing blank list as argument instead of single-element list

I'm writing a function that parses strings into lists that get used by another function. One of the operations that it performs is that it attaches a character to a string inside the (sometimes deeply recursive) list at a particular depth of recursion (the depth defined by a variable named lvl). This operation, a function named listSurgery that is supposed to get called with a list of indices that indicate where the next list is inside the previous list, with the final index telling what index within the deep list to perform an operation at, is getting called with a blank list of indices, and I don't know why. The list that it should be getting called with is [-1], but debugging shows that it's getting called with []. Here is the code, abbreviated:
def listAssign(lst,index,item):
"""Assigns item item to list lst at index index, returns modified list."""
lst[index] = item
return lst
def listInsert(lst,index,item):
"""Inserts item item to list lst at index index, returns modified list."""
print "listInsert just got called with these arguments:",lst,index,item
if index == 'end':
index = len(lst)
lst.insert(index,item)
return lst
def listSurgery(lst,indices,f,*extraArgs):
"""Performs operation f on list lst at depth at indices indices, returns modified list."""
print "listSurgery just got called with these arguments:",lst,indices,f,extraArgs
parent = lst
for index in indices[:-1]:
parent = parent[index]
parent = f(parent,indices[-1],*extraArgs)
return listSurgery(lst,indices[:-1],listAssign,parent)
def parseStringToList(s):
"""Takes in a user-input string, and converts it into a list to be passed into parseListToExpr."""
# ...
l = [] # List to build from string; built by serially appending stuff as it comes up
b = True # Bool for whether the parser is experiencing spaces (supposed to be True if last character processed was a space)
t = False # Bool for whether the parser is experiencing a string of non-alphanumeric characters (supposed to be True if last character was a non-alphanumeric character)
lvl = 0 # Keeps track of depth at which operations are supposed to be occurring
for c in s:
if c == ' ': # If c is a space, ignore it but send signal to break off any strings currently being written to
b = True
# Some elifs for c being non alphanumeric
else: # If c is alphanumeric, append it to the string it's working on
print c,"got passed as an alphanumeric; lvl is",lvl
assert c.isalnum()
if b or t: # If the string it's working on isn't alphanumeric or doesn't exist, append a new string
l = listSurgery(l,[-1]*lvl + ['end'],listInsert,'')
b, t = False, False
l = listSurgery(l,[-1]*(lvl+1),lambda x,y,z:listAssign(x,y,x[y]+z),c)
print l
return l
while op != 'exit' and op != 'quit': # Keep a REPL unless the user types "exit" or "quit", in which case exit
op = raw_input("> ")
if op == 'help':
pass # Print help stuff
elif op in {'quit','exit'}:
pass
else:
print str(parseStringToList(op))
I called the code with python -tt code.py and typed 1+1=2, and this is what I got:
> 1+1=2
1 got passed as an alphanumeric; lvl is 0
listSurgery just got called with these arguments: [] ['end'] <function listInsert at 0x10e9d16e0> ('',)
listInsert just got called with these arguments: [] end
listSurgery just got called with these arguments: [''] [] <function listAssign at 0x10e9d10c8> ([''],)
Traceback (most recent call last):
File "analysis.py", line 276, in <module>
print str(parseStringToList(op))
File "analysis.py", line 218, in parseStringToList
l = listSurgery(l,[-1]*lvl + ['end'],listInsert,'')
File "analysis.py", line 63, in listSurgery
return listSurgery(lst,indices[:-1],listAssign,parent)
File "analysis.py", line 62, in listSurgery
parent = f(parent,indices[-1],*extraArgs)
IndexError: list index out of range
Can anyone explain this? Why is listSurgery getting [] instead of [-1]? lvl is 0, and the argument that's supposed to be passed at that point is [-1]*(lvl+1). Never even mind why it's getting called with [''] instead of '1'.
Your lvl is 0, so [-1]*lvl + ['end'] is ['end'], and indices[:-1] is ['end'][:-1]. Now ['end'] is a list of length 1, so ['end'][:-1] is the same thing as ['end'][:1-1], which is the same thing as ['end'][:0]. This evaluates to empty list.

Python Error: Int object not subscriptable

All right, I'm a novice at python, and here's the snippet of code in question:
<!-- language: lang-py -->
List = [["W","w"],["A","A"],["a","a"]]
def ascii():
x = 0
y = 0
aValues = [[],[],[]]
for item in List:
for item in List[x]:
c = "0"
c = ord(List[x[y]])
y = y + 1
aValues[x].append(c)
x = x + 1
return aValues
aValues = ascii()
print (aValues)
And, when I try to execute this, I get this error message:
>>>
Traceback (most recent call last):
File "/Users/Hersh/Desktop/Python/ascii_conversion.py", line 16, in <module>
aValues = ascii()
File "/Users/Hersh/Desktop/Python/ascii_conversion.py", line 10, in ascii
c = ord(List[x[y]])
TypeError: 'int' object is not subscriptable
>>>
What exactly is the problem, and how can I fix it?
As indicated in the error message, the erroneous line is
c = ord(List[x[y]])
x is an integer (like 0). Instead, you want:
c = ord(List[x][y])
i.e. take the x-th element of List (which is itself a list), and take the y-th element of that.
However, your method of iteration is very unpythonic. You never use the item variables, but you should. For example, a shorter way of writing the line is:
c = ord(item)
By using map and list comprehensions, you can cut down your code to:
def ascii():
return [map(ord, l) for l in List]
I'm not sure of what exactly you intend to do with the function, it has several errors. Try this and tell me if this is what you wanted:
List = [["W", "w"], ["A", "A"], ["a", "a"]]
aValues = [[ord(e1), ord(e2)] for e1, e2 in List]
print(aValues)
EDIT 1 :
Alternatively, if each sublist contains more than two elements, this version is better and will work for the general case:
aValues = [map(ord, pair) for pair in List]
EDIT 2 :
According to the comments, you need to use a function. All right, then let's implement the solution as a function - first thing, the input for the function should be received as a parameter, not as a global variable (List) as you have currently in your code. Then, the result will be returned, and I'll take the opportunity to show yet another way to solve the problem at hand:
def ascii(lst):
return [[ord(element) for element in pair] for pair in lst]
Use it like this:
List = [["W", "w"], ["A", "A"], ["a", "a"]]
ascii(List)
> [[87, 119], [65, 65], [97, 97]]
Hmm. Unfortunately you have quite a lot of issues here. They mostly stem from your misunderstanding of loops in Python.
When you do for item in List, item is set to each element in the list in turn. So, you can't then do for item in List[x] on the next line - that makes no sense. item is the inner list already - so you want to do for inner_item in item (or, call your outer list variable something more sensible).
The next two lines make no sense either. There's no point setting c to "0" then immediately setting it to something else. And don't forget, as I said above, you already have the item in the inner loop, which we've called inner_item. So your code should read c = ord(inner_item).
Hope this helps.
The correct way to index into a 2-dimensional list is not:
c = ord(List[x[y]])
But instead:
c = ord(List[x][y])
Your error comes from the fact that x[y] is an invalid sub-expression, because x is an integer and [] is the subscript operator. You cannot subscript an integer.
However, you don't actually need to index into your list to accomplish the same thing:
def ascii():
x = 0 ## redundant
y = 0 ## redundant
aValues = [[],[],[]]
for item in List:
for item in List[x]: ## you are reusing 'item', change the name here to 'subItem'
c = "0" ## redundant
c = ord(List[x[y]]) ## redundant, replace with: c = ord(subItem)
y = y + 1 ## redundant
aValues[x].append(c)
x = x + 1 ## redundant
Change line 10 to
c = ord(item)
x is not actually an array. It's an integer that you're incrementing.
You need to figure out what it is that you're trying to do, and look up the appropriate syntax for it. It's not very clear what x[y] is supposed to be representing.

Categories