Append element to a list inside nested list - python - python

I am developing a procedure add_to_index, that takes 3 inputs:
an index: [[,[url1,url2,...]],...]
a keyword: String
a url: String
If the keyword is already in the index, url is added to the list of urls associated with that keyword.
If the keyword is not in the index, a new element is to the index:
[keyword,[url]]
CODE
index = []
def add_to_index(index,keyword,url):
flag = 0
count = 0
for lists in index:
count += 1
if(lists[0]==keyword):
index[count][1].append(url)
if(flag ==0):
index.append([keyword,url])
#calling the function below
add_to_index(index,'google','http://google.com')
print index
output -> [['google', 'http://google.com']]
add_to_index(index,'computing','http://acm.org')
print index
output -> [['google', 'http://google.com'], ['computing', 'http://acm.org']]
add_to_index(index,'google','http://gmail.com')
print index
error->
index[count][1].append(url)
AttributeError: 'str' object has no attribute 'append'
Expected output:
[['google', ['http://google.com', 'http://gmail.com']],
['computing', ['http://acm.org']]]

You have done three mistakes, Firstly you have not used the flag and secondly you are adding the url as a string. And finally as Kaivosuketaja has mentioned in the comment, count should be incremented in the end. It can be done otherwise as
index = []
def add_to_index(index,keyword,url):
flag = 0
count = 0
for lists in index:
if(lists[0]==keyword):
flag = 1
index[count][1].append(url)
count += 1
if(flag ==0):
index.append([keyword,[url]])
# Take note of append away here
#calling the function below
add_to_index(index,'google','http://google.com')
print index
add_to_index(index,'computing','http://acm.org')
print index
add_to_index(index,'google','http://gmail.com')
print index
The output now is
[['google', ['http://google.com']]]
[['google', ['http://google.com']], ['computing', ['http://acm.org']]]
[['google', ['http://google.com', 'http://gmail.com']], ['computing', ['http://acm.org']]]

I think this is what you want:
index = []
def add_to_index(index,keyword,url):
flag = 0
count = 0
for lists in index:
if lists[0] == keyword:
lists[1].append(url)
flag = 1
count += 1
if flag == 0:
index.append([keyword, [url]])
#calling the function below
add_to_index(index,'google','http://google.com')
print index

I will suggest the use of dictionaries for this:
index = {}
def add_to_index(index, keyword, url):
if keyword not in index:
index[keyword] = [url]
else:
index[keyword].append(url)
>>> add_to_index(index,'computing','http://acm.org')
>>> add_to_index(index,'google','http://gmail.com')
>>> add_to_index(index,'google','http://gmail.com')
>>> index
{'computing': ['http://acm.org'], 'google': ['http://gmail.com', 'http://gmail.com']}
You could even make index a non global variable by implementing a simple class(ofcourse, this is possible with nested lists too):
class Index(object):
def __init__(self):
self.index = {}
def add_to_index(self, keyword, url):
if keyword not in index:
self.index[keyword] = [url]
else:
self.index[keyword].append(url)

First, you're trying to append to a string that is inside of the list you want to append to. Then, you forgot to say flag = 1 when you've found the keyword. Try the following:
index = []
def add_to_index(index,keyword,url):
flag = 0
count = 0
for lists in index:
if(lists[0]==keyword):
index[count][1].append(url)
flag = 1
count += 1
if(flag ==0):
index.append([keyword,url])
#calling the function below
add_to_index(index,'google','http://google.com')
add_to_index(index,'computing','http://acm.org')
add_to_index(index,'google','http://gmail.com')
print index
I think you'd be much better off using a defaultdict, though. It automatically searches for a keyword and adds the item to the existing keyword, or if it isn't found, creates a new keyword.

You could simplify things a little by getting rid of the flag and count variables.
index = []
def add_to_index(index, keyword, url):
for e in index:
if e[0] == keyword:
e[1].append(url)
return
else:
index.append([keyword,[url]])

Related

define a function to check if a list of elements is palindrome and returns a list

I have to do the following:
Define a function called isSymmetricalVec that takes a list of elements, checks if each element in a list is palindrome, then returns their results in a list. For example, given ["1441", "Apple", "radar", "232", "plane"] the function returns [TRUE, FALSE, TRUE, TRUE, FALSE].
I wrote the following code but I'm stuck at the point where I cannot return the result in a list.
def isSymmetricalVec(myList):
for myString in myList:
myList = []
mid = (len(myString)-1)//2
start = 0
last = len(myString)-1
flag = 0
while(start<mid):
if (myString[start]== myString[last]):
start += 1
last -= 1
else:
flag = 1
break;
if flag == 0:
print(bool(1))
else:
print(bool(0))
# Enter a list of strings to check whether it is symmetrical or not
myList = ["12321", "12345", "madam", "modem"]
isSymmetricalVec(myList)
My function returns the following but the result is not in a list format:
True
False
True
False
How can I modify my code to return a result in a list format?
You function should return value instead of printing it.
Created an empty list new_list and appended result to it.
def isSymmetricalVec(myList):
new_lst = []
for myString in myList:
mid = (len(myString) - 1) // 2
start = 0
last = len(myString) - 1
flag = 0
while (start < mid):
if (myString[start] == myString[last]):
start += 1
last -= 1
else:
flag = 1
break;
if flag == 0:
new_lst.append(True)
else:
new_lst.append(False)
return new_lst
# Enter a list of strings to check whether it is symmetrical or not
Your function is actually not returning anything. What you see are only being printed and not returned.
You would want to keep each answer in a list like this.
def isSymmetricalVec(myList):
list_of_answers = []
for myString in myList:
...
while(start<mid):
...
if flag == 0:
print(bool(1))
list_of_answers.append(True)
else:
print(bool(0))
list_of_answers.append(False)
return list_of_answers
This way your answers are printed and returned.
Finally, you would need a variable to hold the returned list.
# Enter a list of strings to check whether it is symmetrical or not
myList = ["12321", "12345", "madam", "modem"]
list_of_answers = isSymmetricalVec(myList)
def isSymmetricalVec(myString):
mid = (len(myString)-1)//2
start = 0
last = len(myString)-1
flag = 0
while(start<mid):
if (myString[start]== myString[last]):
start += 1
last -= 1
else:
flag = 1
break;
if flag == 0:
return True
else:
return False
test = ["1221", "madam", "hello world"]
final = [isSymmetricalVec(i) for i in test]
print(final)
I rewrote the code a bit and this would be my solution. It retains the original functionality and is stylish as well as efficient. It also makes the original function more flexible and makes it easily migratable.
Your function doesn't return anything, just printing values.
There is a good way to shorten your algorithm with python slices. Also this function returns list of boolean objects.
from math import ceil, floor
def isSymmetricalVec(myList):
list_of_answers = []
for string in myList:
strLength = len(string)
#There is a string palindrome check
if string[:floor(strLength//2)] == string[ceil(strLength/2):][::-1]:
toAppend = True
else:
toAppend = False
list_of_answers.append(toAppend)
return list_of_answers
It is worth adding that it's better to use True and False instead of bool(1) and bool(0).
An example:
>>> isSymmetricalVec(['11211', 'AbbA', '12f23'])
>>> [True, True, False]

looping over a nested list with multiple rows and columns

I wanted to replace the items from listoflist = [[None, None, None]] with the output from
def _execute():
user_input = input("type in: ")
return user_input
without creating a new list
def insertdata(data): is doing that. its start with the first value and continues till the last value
def insertdata(data):
data_added = False
n = len(listoflist[0])
index = 0
while not data_added and index != n:
if listoflist[0][index] is None:
listoflist[0][index] = data
data_added = True
else:
index += 1
if index == n:
print("\n The list is full, No more elements will be added \n")
while True:
insertdata(_execute())
print(listoflist)
I want to extend the function to loop over a nested list with multiple rows.
what condition should the if statment have so it starts at the first row and execute the inner loop `?
def double_loop(data):
data_added_outer = False
index_outer = 0
n_out = len(listoflist)
# outer loop
while not data_added_outer and index_outer < n_out:
if: # what condition ?
#### inner loop ###############
data_added_inner = False
n_inner = len(listoflist[index_outer])
index_inner = 0
while not data_added_inner and index_inner != n_inner:
if listoflist[index_outer][index_inner] is None:
listoflist[index_outer][index_inner] = data
data_added = True
else:
index_inner += 1
if index_inner == n_inner:
print("\n The list is full, No more elements will be added \n")
####### inner ############################################################
else:
index_outer += 1
if index_outer == n_out:
print("\n The list is full, No more elements will be added \n")
Instead of replacing the data, the elegant approach in Python is to create new data, using comprehensions:
def with_nones_replaced(grid, replacement):
return [
[
replacement if value is None else value
for value in row
]
for row in grid
]
As far as I have understood, the job of your function is simply to replace the None objects in a 2D-List with the data parameter passed to the function. I find a for-loop approach much more cleaner, and pythonic in this case.
def changedata(arr, data):
for item in arr:
for x in range(len(item)):
if item[x] is None:
item[x] = data
You can also use the map function to simplify the code:
def changedata(arr, data):
for i in range(len(arr)):
arr[i] = list(map(lambda x: data if x is None else x, arr[i]))
If the data is coming from a function, you can still use this paradigm by calling
_execute() once, storing it in a variable, and then passing it to changedata()
data = _execute()
changedata(listoflist, data)
print(listoflist)

Adding to a Python Dictionary

def countFrequency(L):
fdict = {}
for x in range(0, len(L)):
for key, value in fdict:
if L[x] == fdict[str(x)]:
value = value + 1
else:
fdict[L[x]] = 1
return fdict
I'm trying to count the frequency of occurrences of a particular symbol in a given string and create a dictionary out of this. For some reason, the function just returns an empty dictionary. I think the problem arises with adding a new value to the dictionary, but not sure how to troubleshoot it/fix it.
input: countFrequency('MISSISSIPPI')
output: {}
Do this:
def countFrequency(L):
fdict = {}
for x in range(0, len(L)):
if str(L[x]) in fdict.keys():
fdict[str(L[x])] = fdict[str(L[x])] + 1
else:
fdict[str(L[x])] = 1
return fdict
The code in the inner loop:
if L[x] == fdict[str(x)]:
value = value + 1
else:
fdict[L[x]] = 1
is unreachable, because the dictionary is empty initally, and hence you will never add any value to fdict.
you can do it likes this:
def countFrequency(L):
fdict = {}
for symbol in L: #gets each letter in l
if symbol in fdict: #check if dhe dictionary already has an value for the symbol
fdict[symbol] += 1
else:
fdict[symbol] = 1
return fdic
Another issue is that the value value is never assigned to anything or used, so even if we were to go through the loop we would never increment a value in the dictionary.

making a function that takes a list as input and return count of the string “bebo” in that list

I want a function called bebo_count that takes a list x as input and returns the count of the string “bebo” in that list.
For example, bebo_count(["bebo","buzz","bebo"]) should return 2
i have made a code like this
def bebo_count(x):
for a in x:
count = 0
if a == "bebo":
count += 1
return count
but it doesn't work it's always return 1 to me,can any one please modify this code to be working well?!
You keep resetting count = 0 in your loop, move it outside:
def bebo_count(x):
count = 0
for a in x:
if a == "bebo":
count += 1
return count
do not reinvent the wheel :-)
There is a built in method count
x = [ "bebo", "bv", "bebo" ]
x.count("bebo")
> 2
x.count("b")
> 0
You are setting count = 0 inside the for loop. That means that at each loop iteration, irrespective of what the value of count was before, it gets set back to zero. You should initialize count outside the loop. Note also that I have corrected your indentation.
def bebo_count(x):
count = 0
for a in x:
if a == "bebo":
count += 1
return count
For your reference, here is another way you might write this same function:
def bebo_count(x):
return len([a for a in x if a == "bebo"])
Your problem is: count = 0 is inside your for loop.
To fix your code :
def bebo_count(x):
count = 0 # initialize the count before you start counting
for a in x:
if a == "bebo":
count += 1
return count
However, a more pythonic way could be using list comprehension:
big_list = ["bebo", "something else", "bebo"]
def bebo_count(big_list) :
return len( [x for x in big_list if x=="bebo" ] )
print( bebo_count(big_list))

how to change the value of a variable inside an if loop each time the if loop is triggered ?

i am trying to use codeacademy to learn python. the assignment is to "Write a function called fizz_count that takes a list x as input and returns the count of the string “fizz” in that list."
# Write your function below!
def fizz_count(input):
x = [input]
count = 0
if x =="fizz":
count = count + 1
return count
i think the code above the if loop is fine since the error message ("Your function fails on fizz_count([u'fizz', 0, 0]); it returns None when it should return 1.") only appears when i add that code.
i also tried to make a new variable (new_count) and set that to count + 1 but that gives me the same error message
I would appreciate your assistance very much
The problem is that you have no loop.
# Write your function below!
def fizz_count(input):
count = 0
for x in input: # you need to iterate through the input list
if x =="fizz":
count = count + 1
return count
There is a more concise way by using the .count() function:
def fizz_count(input):
return input.count("fizz")
Get rid of x = [input], that just creates another list containing the list input.
i think the code above the if loop is fine
ifs don't loop; you're probably looking for for:
for x in input: # 'x' will get assigned to each element of 'input'
...
Within this loop, you would check if x is equal to "fizz" and increment the count accordingly (as you are doing with your if-statement currently).
Lastly, move your return-statement out of the loop / if-statement. You want that to get executed after the loop, since you always want to traverse the list entirely before returning.
As a side note, you shouldn't use the name input, as that's already assigned to a built-in function.
Putting it all together:
def fizz_count(l):
count = 0 # set our initial count to 0
for x in l: # for each element x of the list l
if x == "fizz": # check if x equals "fizz"
count = count + 1 # if so, increment count
return count # return how many "fizz"s we counted
def fizz_count(x): #DEFine func
count = 0 #set counter to zero
for item in x:
if item == "fizz" :
count += 1 #iterate counter +1 for each match
print count #print result
return count #return value
fizz_count(["fizz","buzz","fizz"]) #call func
Try this:
# Write your function below!
def fizz_count(x):
count = 0
for item in x:
if item == "fizz":
count = count + 1
return count
def fizz_count(input)
count = 0
for x in input:
count += 1 if x=="fizz" else 0
return count

Categories

Resources