I would like to ask for some help with python ask since im new and im trying to learn it.
Write the following functions.
empty_list() returns an empty "list" of songs. This doesn't have to be a list in a Python sense of a word: the function can return a list, a tuple, dictionary, string, None ... or even a number if you think this is a good idea. (Hint: it's not. :) Return something that will be useful un the following functions.
play(a_list, song) somehow adds the given song (a string) to the list. How it does it depends on what your list is (a list, dictionary...).
song_plays(a_list, song) returns the number of times the song was played.
Say we do this:
new_list = empty_list()
play(new_list, "Yesterday")
play(new_list, "Tomorrow")
play(new_list, "Yesterday")
play(new_list, "Yesterday")
After this, a call song_plays(new_list, "Yesterday") returns 3, call song_plays(new_list, "Tomorrow") returns 1, and call song_plays(new_list, "Today") returns 0.
First part is done but now i need to write 4 more functions which i dont know where to start.
In the following functions we assume that we have two lists.
number_of_common(list1, list2) returns the number of songs that appear on both lists.
repertoire_size(list1, list2) returns the number of songs that appear on one (or even both) lists.
similarity(list1, list2) returns the similarity computed as the quotient of the above two numbers. If both lists are empty, the similarity is 0.
Write a function rang(a_list, n) that returns a list of the n most played songs. If two songs share equal number of plays, sort them alphabetically. If the list contains less than n song, the returned list will be shorted (but still ordered).
This is what i have for now:
def empty_list():
list = {}
return list
def play(list, song):
if song in list:
list[song] += 1
else:
list[song] = 1
def song_plays(list, song):
if song not in list:
return 0
else:
return list[song]
def total_songs(list):
return len(list)
def total_plays(list):
totalplays = 0
for name in list:
a = list[name]
totalplays += a
return totalplays
def favourite(list):
if list == {}:
return None
else:
max_name = ''
max_a = 0
for name in list:
a = list[name]
if max_a < a:
max_a = a
max_name = name
return max_name
def number_of_common(list1,list2):
def repertoire_size(list1,list2):
def similarity(list1,list2):
def rang(list,n):
For the list datatype, I'd recommend a Counter, then everything gets pretty compact:
from collections import Counter as empty_list
def play(a_list, song):
a_list[song] += 1
def song_plays(a_list, song):
return a_list[song]
def number_of_common(list1, list2):
return len(set(list1) & set(list2))
def repertoire_size(list1, list2):
return len(list1 + list2)
def similarity(list1, list2):
try:
return number_of_common(list1, list2) / repertoire_size(list1, list2)
except ZeroDivisionError:
return 0
def rang(a_list, n):
ranks = sorted(a_list.most_common(n), key = lambda x: (-x[1],x[0]))
return [song for song, times in ranks]
For the first three functions, look to the set data type. Set union, intersection, and length will solve these problems quickly. For instance:
set1 = set(list1)
set2 = set(list2)
either = set1.union(set2)
both = set1.intersection(set2)
full_count = len(either)
both_count = len(both)
similarity = float(both_count) / full_count
Note that within a single function, you can easily reduce the computations to a single line, such as
both_count = len(set(list1).intersection(set(list2)))
Sort by play frequency
You should be able to find supporting code through this sorting tutorial. The list is your main list; the play frequency is the sort key.
Related
Write a Python function that will take a the list of 100 random integers between 0 and 1000 and return the maximum value. (Note: there is a builtin function named max but pretend you cannot use it.)
Here's what I tried:
import random
list = []
for i in range(100):
list.append(random.randint(0,1000))
def max(list):
#sort list from least to greatest
answer = list.sort()
#get last item in list (max value)
list.pop()
return max
print (max(list))
As you can see, what I'm confused about is how to correctly use the sort and pop methods to return the max value within the max function. I'm currently getting:
ParseError: bad input on line 12
Which is this line:
list.pop()
Not sure how to correct this. Thanks.
1) Your indentation was off
2) You managed to overwrite 2 Python builtins in 4 lines of code (max() and list()))
3) my_list.sort() does not return a list. It operates in place sorting the list in-place. On the contrary, sorted(my_list) does return a list so you can either do my_list.sort() or my_list = sorted(my_list).
4) Your return was just wrong.
See the code below:
a_list = []
for i in range(100):
a_list.append(random.randint(0, 1000))
def my_max(my_list):
return sorted(my_list)[-1] # here, the list we passed gets sorted and its last item is retrieved (item with index -1)
print(my_max(a_list))
Other interesting answers (hats off to #Rob) that feature a bit of cockiness:
def my_max(my_list):
return min(l, key:lambda i: 1/i)
or
def my_max(my_list):
return min(l, key:lambda i: -i)
my_list.sort() sorts the list itself. If you want to store your sorted list in answer, you should use:
answer = sorted(my_list)
You can also use a list comprehension to generate your first list as follows:
>>> random
>>>
>>> my_list = [random.randint(0, 1000) for i in range(100)]
>>> answer = sorted(my_list)
>>> answer.pop()
996 # This should be different each time
Now, your function can be:
def max(my_list):
# sort list from least to greatest
answer = sorted(my_list)
# get last item in list (max value)
max = answer.pop()
return max
If you still want to use the same list, you can do:
my_list.sort()
max = my_list.pop()
Note that: I prefer to call the list my_list because list is a python keyword.
I usually try to avoid using names that are have a predefined function / built-in names, this helps to avoid problems quite often. Like this it should work.
import random
my_list = []
for i in range(100):
my_list.append(random.randint(0,1000))
def my_max(my_list):
#sort list from least to greatest
my_list.sort()
#get last item in list (max value)
my_max = my_list.pop()
return my_max
print my_max(my_list)
Im not sure how to get my recursion to work properly or keep from infinitely repeating.
This is what i have so far:
def listSquareR(lst):
if len(lst)== 1:
return lst[0]**2
else:
return lst[0]**2+[listSquareR(lst[1:])]
last return line is obviously wrong
Another possibility:
def listSquare(L):
if L: return [L[0]**2] + listSquare(L[1:])
else: return []
An even shorter version (as Cristian Ciupitu mentions below) is:
def listSquare(L):
return [L[0]**2] + listSquare(L[1:]) if L else []
You have it almost right, but the key is to mind your types. In your code:
def listSquareR(lst):
if len(lst)== 1:
return lst[0]**2 # Returning a number
else:
return lst[0]**2+[listSquareR(lst[1:])] # Returning a number plus a list of a list
We just need two small fixes:
def listSquareR(lst):
if len(lst)== 1:
return [lst[0]**2] # Returning a list
else:
return [lst[0]**2] + listSquareR(lst[1:]) # Returning a list plus a list
def SquareArea(width):
if width == 0:
return 0
else:
return SquareArea(width-1) + (2*width-1)
This is a recursive function I've recently used to find the area of a square.
And since the area of a square is Side*Side, one can use it to find the square of any function.
Now all that is required of you is to make a loop, eg:
for i in range (list):
and implement this function on i
Or maybe use while loop.
newList=[]
length = len(list)
while i != length:
newList.append(SquareArea(i))
And then return the newList
(Using python 3.3.2) Hi, I'm trying to make a crawling function for a text cloud, which would go into a list of links and ideally return a list of the function's output for each element in that list. However, I'm stuck using a print function, print(b), instead of actually returning what I want. In my for loop, how would I return everything I would get from my print(b) statement. It can all be in one list or compiled some way or another. Thank you :)
tl;dr: how do I return all the stuff I get from a for loop
def crawl():
linkList = inputFunction()[1:][0] #makes a list of a bunch of URL's
for i in range(len(linkList)):
print(i)
t = getHTML(linkList[i]) #getHTML returns tuple of text in the input URL
alreadyCrawl = alreadyCrawl + list(linkList[i]) #ignore this
t = list(t)
b = counting(t) #makes dictionary of word counts
print(b)
return
Either you put them in a list and return the list at the end, or you "yield" them (hence creating a generator).
First way:
def f():
acc = []
for x in range(10):
acc.append(someFunctionOfX(x))
return acc
Second way:
def g():
for x in range(10):
yield someFunctionOfX(x)
Maybe the most important difference is the following: If any call to someFunctionOfX causes an exception in example 1, the function won't return anything. In example 2 if let's say the 5th value cannot be yielded for some reason, the previous four have already been yielded and probably used in the caller's context.
Here you can see the difference:
def f():
acc = []
for x in range(-3, 4):
acc.append (2 / x)
return acc
def g():
for x in range(-3, 4):
yield 2 / x
def testF():
for x in f(): print(x)
def testG():
for x in g(): print(x)
Calling testF simply fails (ZeroDivisionError: division by zero) and doesn't print anything. Calling testG prints
-0.6666666666666666
-1.0
-2.0
and fails then (ZeroDivisionError: division by zero).
My (very personal) criterion for either returning a list or yielding values is the following: If I need the data stored somewhere, I return a list. If I just need to process each member, I yield them.
You can return list of values that you want.
def crawl():
list_ret = [] #create empty list to store values
for i in range(len(linkList)):
# do some stuff
b = counting(t) #makes dictionary of word counts
list_ret.append(b) #append value to list
print(b)
return list_ret #return list of values
def crawl():
linkList = inputFunction()[1:][0] #makes a list of a bunch of URL's
return_list = []
for i in range(len(linkList)):
print(i)
t = getHTML(linkList[i]) #getHTML returns tuple of text in the input URL
alreadyCrawl = alreadyCrawl + list(linkList[i]) #ignore this
t = list(t)
b = counting(t) #makes dictionary of word counts
return_list.append(b)
return return_list
I have a list of the following kind:
class Ind(object):
def __init__(self,ID,mate):
self.ID=ID
self.mate=mate
population=[Ind(8,None), Ind(1,2), Ind(20,3), Ind(2,1), Ind(12,None), Ind(3,20), Ind(10,11), Ind(11,10)]
You can think of this list population as a population of individuals which all have an ID. Some of them have a mate (an individual who is present in the same population or the same list). The mate value is actually the ID of the mate! Therefore, if there is an instance of Ind which attributes ID equals 12 and mate equals 34, then there is necessarily an individual in the list whose ID equals 34 and whose mate equals 12. Individuals that do not have a mate have None in the mateattribute. Does it make sense?
I'd like to sort this list so that the first individual mates with the last one, the second individual mates with the second-to-last individual, etc... The individual which attribute mateequals None should stand in the middle of the list.
There are many possible outputs that fit what I want. Here is one example of these outputs for the above list:
population=[Ind(1,2), Ind(20,3), Ind(10,11), Ind(8,None), Ind(12,None), Ind(11,10), Ind(3,20), Ind(2,1)]
You can try something like this:
def custom_sort(population):
pop_dict = { ind.ID: ind for ind in population }
start = []
nones = []
end = []
for ind in population:
if ind.mate is None:
nones.append(ind)
elif pop_dict[ind.mate] not in start:
start.insert(0, ind)
end.append(pop_dict[ind.mate])
return start + nones + end
This is under assumption that "being a mate" is a 1-to-1 relation.
You just need a key for the sorting function. The following example requires that individuals are monogamous and not married to themselves. It also requires that if (a,b) is listed, (b,a) is also listed. If these prerequisites are not met and Ind(2,1) can occur without Ind(1,2), this function will place Ind(2,1) towards the end of the list. The first index in the key function is the type: "first" in relationship (where IDmate) comes third. These first and second types are sorted in order by their ids; last type is sorted in reverse order by its mate.
def keyfun(x):
if x.mate==None:
return (1,x.ID)
elif x.ID<x.mate:
return (0,x.ID)
else:
return (2,-x.mate)
sorted(population,key=keyfun)
Another way to handle this, still assuming that if (a,b) is in the list (b,a) will also be in the list, is to just preprocess by removing (b,a) cases, then postprocess by adding them back in in reverse order.
How about this. Split list into three lists, one with ID < mate, the second with ID > mate, and the third with mate is None. Then, concatenate the sorted lists, each sorted via ID.
I've added a __repr__ method to the Ind class for output readability.
class Ind(object):
def __init__(self,ID,mate):
self.ID=ID
self.mate=mate
def __repr__(self):
return 'Ind({},{})'.format(self.ID,self.mate)
population=[Ind(8,None), Ind(1,2), Ind(2,3), Ind(2,1), Ind(12,None), Ind(3,2), Ind(10,11), Ind(11,10)]
def custom_sort(pop):
singles, less, more = [], [], []
for p in pop:
if p.mate is None:
singles.append(p)
elif p.ID < p.mate:
less.append(p)
elif p.ID > p.mate:
more.append(p)
comp = lambda x,y: cmp(x.ID,y.ID)
return sorted(less,cmp=comp) + sorted(singles,cmp=comp) + sorted(more,cmp=comp,reverse=True)
print custom_sort(population)
This outputs:
[Ind(1,2), Ind(2,3), Ind(10,11), Ind(8,None), Ind(12,None), Ind(11,10), Ind(3,2), Ind(2,1)]
There is a lot you can do with costum key functions:
def my_key(ind):
if ind.mate is None:
return 0
if ind.ID < ind.mate:
return -ind.ID - 1
else:
return ind.mate + 1
population.sort(key=my_key)
This assumes that IDs will never be negative. If IDs are always greater than 0, you can discard the - 1 and + 1.
I have a method, that computes the number of differences in two strings, and outputs where the differences are.
def method(a):
count=0
s1="ABC"
for i in range (len(a)):
if not a[i]==s1[i]:
count=count+1
else:
count=count+0
return a,count,difference(a, s1)
On input ex CBB, this method outputs
('CBB', 2, [1, 0, 1])
What I really need is for this method to do the same, but where is not only compares to a single string in s1, but to a list of strings
s1 = ['ACB', 'ABC', 'ABB']
Anyone with a smart method to do this?
Ok, after clarification, instead of hardcoding s1, make your method take it as argument:
def method(a, s1):
count=0
for i in range (len(a)):
if not a[i]==s1[i]:
count=count+1
else:
count=count+0
return a,count,difference(a, s1)
Then use list compherension:
result = [method(a, s1) for s1 in list]
Be careful though, as your method will fail if a is longer than s1. As you really don't say what the result should be in that case, i left it as is.
the compare function calculates the number of differences (and map of differences that you had been creating with difference()). I rewrote the compare function to take a base string to be compared to, src, so that you don't get stuck with comparing to "ABC" all the time.
def compare(src, test):
if len(src) != len(test):
return # must be the same length
diffmap = [0]*len(src)
count = 0
for i, c in enumerate(src):
if not c == test[i]:
count = count+1
diffmap[i] = 1
return test, count, diffmap
The compare_to_many function simply goes through a list of strings to compare to, srcs, and creates a list of the comparisons between those base strings and a test string test.
def compare_to_many(srcs, test):
return map(lambda x: compare(x, test), srcs)
EDIT:
After clarification in the comments, #X-Pender needs the source list to be hardcoded. This can be reflected by the following, single function:
def compare(test):
def compare_one(src, test):
diffmap = [0]*len(src)
count = 0
for i, c in enumerate(src):
if not c == test[i]:
count = count+1
diffmap[i] = 1
return test, count, diffmap
sources = ["ABC", "CDB", "EUA"] # this is your hardcoded list
return map(lambda x: compare_one(x, test), sources)