My dictionary as of now is like this:
class_1 = {'Bob':[9,5,4,3,3,4], 'John':[5,5,7,3,6], 'Andy':[7,5,6,4,5], 'Harris':[3,4,2,3,2,3,2]}
What i am trying to make it look like is this:
class_1_average ={'Bob':[average of scores],'John':[average of scores].........
How can i do this so that even when the scores updates the average also updates with it. And is there also a way to find the highest score out of the scores
try like this:
class_1_average = {key: sum(value)/len(value) for key, value in class_1.items()}
For max value: you can use max built-in function over the value of dictionary
max_each = {key: max(value) for key, value in class_1.items()}
You can use numpy.mean in a generator expression to get the average for each student. You can use this paradigm in general to get other statistics.
>>> from numpy import mean
>>> class_1 = {'Bob':[9,5,4,3,3,4], 'John':[5,5,7,3,6], 'Andy':[7,5,6,4,5], 'Harris':[3,4,2,3,2,3,2]}
>>> class_1_average = {name: mean(values) for name, values in class_1.items()}
>>> class_1_average
{'John': 5.2000000000000002, 'Harris': 2.7142857142857144, 'Andy': 5.4000000000000004, 'Bob': 4.666666666666667}
One thing that comes to mind if you need to keep your averages updated "in real time" (although is probably killing flies with nuclear weapons and not really what you need) would be creating a custom class that inherits from the builtin dict type and extend it with an averages method:
import pprint
class MyDict(dict):
def averages(self):
averages = {}
for name, score_list in self.iteritems():
averages[name] = sum(score_list) / len(score_list)
return averages
if __name__ == "__main__":
class_1 = MyDict({
'Bob': [9, 5, 4, 3, 3, 4],
'John': [5, 5, 7, 3, 6],
'Andy': [7, 5, 6, 4, 5],
'Harris': [3, 4, 2, 3, 2, 3, 2]
})
print "class_1: %s" % pprint.pformat(class_1)
print "class_1_averages: %s" % pprint.pformat(class_1.averages())
print "Bob's average: %s" % pprint.pformat(class_1.averages()['Bob'])
print "Setting Bob's scores to [1, 1, 1]"
class_1['Bob'] = [1, 1, 1]
print "Bob's average: %s" % pprint.pformat(class_1.averages()['Bob'])
That outputs:
class_1: {'Andy': [7, 5, 6, 4, 5],
'Bob': [9, 5, 4, 3, 3, 4],
'Harris': [3, 4, 2, 3, 2, 3, 2],
'John': [5, 5, 7, 3, 6]}
class_1_averages: {'Andy': 5, 'Bob': 4, 'Harris': 2, 'John': 5}
Bob's average: 4
Setting Bob's scores to [1, 1, 1]
Bob's average: 1
Maybe you can use this as an idea of what Python allows you to do (which doesn't necessarily mean that you should be doing it this way) You're probably much better off with Hackaholic's answer.
Related
Suppose I have two lists A, B such that A is a subset of B. If I were to parse through the points of B and each time I want to test if an element is a member of A, would representing A as a dictionary be better than as a list? I ask because I am under the impression that dictionaries have worst case lookup time O(1), whereas for arrays it is O(n).
That is, which of the following would be more efficient in terms of time complexity?
# Code 1
A = [1, 2, 3]
B = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 1, 2, 3]
for i in B:
if i in A:
print (i)
else:
print (-1)
# Code 2
A = [1, 2, 3]
B = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 1, 2, 3]
A_dict = {}
for i in A:
A_dict[i] = 0
for i in B:
if i in A_dict:
print (i)
else:
print (-1)
It seems that if what I said about time complexities above is true, then the first code has complexity O(|B| x |A|), whereas the second has complexity O(|B|). Is this correct?
You should use sets for that. They have O(1) lookup, like dicts, but they aren't key-value pairs.
Your code would then look like this:
A = [1, 2, 3]
B = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 1, 2, 3]
A_set = set(A)
for i in B:
if i in A_set:
print (i)
else:
print (-1)
or:
A = {1, 2, 3}
...
Basically I have dictionary with each key-pair having its value as a list. Reason, is so that I can insert or append additional values into the list later on.
Like this, each key pair is:
'A' : [2]
To make testing code faster, I hard coded a portion of the playerDict like this:
playerDict = {"A" : [2], "B" : [2], "C" : [2]}
I also allowed a way to enter additional key-pairs. So I can manually enter additional key-pair 'D' and 'E'
{'A': [2], 'B': [2], 'C': [2], 'D': [2], 'E': [2]}
Looks exactly the same when I print out the playerDict. However, behaviour is different when I run it through a for loop to insert/append values into the list.
{'A': [2, 5, 1, 4], 'B': [2, 6, 5, 1], 'C': [2, 6, 5, 1], 'D': [2, 8, 6, 1, 5, 5, 3], 'E': [2, 8, 6, 1, 5, 5, 3]}
Behaviour for A, B and C is what I want, which is only 1 insertion at index 1 of the list and 2x appending at the end of the list for each key-pair.
However, for the manually entered key-pair, it gets inserted and appended how many times I manually placed a key-pair in. Place in 2 key-pair, 2 times, place in 3 key-pair, it gets inserted and appended 3 times.
{'A': [2, 6, 2, 4], 'B': [2, 3, 1, 2], 'C': [2, 6, 4, 2], 'D': [2, 9, 10, 11, 5, 6, 4, 6,6, 3], 'E': [2, 9, 10, 11, 5, 6, 4, 6, 6, 3], 'F': [2, 9, 10, 11, 5, 6, 4, 6, 6, 3]}
Its driving me nuts since I'm unsure what is the difference between my hard-coded key-pairs and the manually entered ones. How can I get my desired behaviour?
import random
def rollDice():
return random.randint(1, 6)
def getPlayers(playerDict):
points = [2]
while True:
name = str(input("Enter player name, <Enter> to end: "))
if name == "":
break
else:
playerDict[name] = points
print(playerDict, "adding a user")
return playerDict
def startGame(playerDict):
print("Start game. Roll 2 dice per player")
for names, stats in playerDict.items():
rollstart1 = rollDice()
rollstart2 = rollDice()
total = rollstart1 + rollstart2
stats.insert(1, total)
stats.append(rollstart1)
stats.append(rollstart2)
print("{}, dice: ({}, {}), total {}".format(names, stats[2], stats[3], stats[1]))
return playerDict
def main():
#playerDict = {}
playerDict = {"A" : [2], "B" : [2], "C" : [2]}
playerDict = getPlayers(playerDict)
playerDict = startGame(playerDict)
print(playerDict)
main()
You want a fresh new list for each player... not the same list for all of them; changing the code to
playerDict[name] = [2]
should do the trick.
It is important to understand that with Python assignment doesn't copy objects. If you want to make a copy you need to ask explicitly so:
a = [2]
b = a
a.append(12)
print(b) # will print [2, 12] because a and b reference the same list object
In Python the "list literal" [2] isn't indeed a list... but a "list constructor" that creates a new separate list object each time is evaluated.
I'm new to Python and I am trying to make a calculator for a game. I would like to get the max integer at a specific index between lists (that are values in the dictionary) and the key that the max value came from.
I've tried to loop through the dictionary.
raw_player_score = {'Matt' : [3, 5, 5, 4, 6, 9],
'Kyle' : [6, 9, 11, 5, 4, 3],
'Emily' : [4, 4, 5, 2, 1, 5]}
def extra_points(dict):
for k, v in dict.items():
for number in v:
apple_king = max(v[1])
print(apple_king)
final_dict = extra_points(raw_player_score)
I would expect the outcome to be 9 since Kevin has the highest number at index 1, but instead, I get the message "'int' object is not iteratable'
All of the suggestions in the other answers are spot on. I'll offer up a simpler, old-school solution that does the minimal amount of work, not having to create any additional lists or do any sorting. I figure that as a new Python programmer, you might be best served by the most direct and transparent approach:
raw_player_scores = {'Matt' : [3, 5, 5, 4, 6, 9],
'Kyle' : [6, 9, 11, 5, 4, 3,],
'Emily' : [4, 4, 5, 2, 1, 5]}
def extra_points(scores, pos):
max_score = 0
max_key = None
for k, v in scores.items():
if v[pos] > max_score:
max_score = v[pos]
max_key = k
return max_key
max_key = extra_points(raw_player_scores, 1)
print(max_key)
Result:
Kyle
It is not good idea to hardcode the needed index; I recommend you to move it to an argument. Other changes are commented:
def extra_points(dict_, index):
return max( # Return maximum
( # From iterator
(name, score_list[index]) # For name-score[index] tuples
for name, score_list in dict_.items() # In dict_
),
key=lambda x: x[1] # Check the max by score[index]
)[0] # Get the name (zero element)
raw_player_score = {
'Matt': [3, 5, 5, 4, 6, 9],
'Kyle': [6, 9, 11, 5, 4, 3,],
'Emily': [4, 4, 5, 2, 1, 5]
}
print(extra_points(raw_player_score, 1))
Kyle
Try not to use dict as a variable name, you can try:
raw_player_score = {'Matt': [3, 5, 5, 4, 6, 9], 'Kyle': [6, 9, 11, 5, 4, 3], 'Emily': [4, 4, 5, 2, 1, 5]}
def extra_points(d, ind):
values_at_index = []
for key in d:
values_at_index.append((key, d[key][ind]))
return max(values_at_index, key=lambda x: x[1])
print(extra_points(raw_player_score, 1))
print(extra_points(raw_player_score, 1)[0])
which gives:
('Kyle', 9)
Kyle
I'm new to Python and was trying to create a new dictionary from a dictionary with values in list format. Below please find my code:
dataset = {
"a" : [3, 1, 7, 5, 9],
"b" : [4, 8, 7, 5, 3],
"c" : [3, 4, 1, 0, 0],
"d" : [0, 5, 1, 5, 5],
"e" : [3, 7, 5, 5, 1],
"f" : [3, 6, 9, 2, 0],
}
for v in dataset.values():
total = (sum(v))
print(total)
for k in dataset:
print(k)
dict1 = {k:total for k in dataset}
print(dict1)
My expected result is {"a":25, "b":27, ..}.
Instead, when i run the codes, the output is
{'a': 20, 'b': 20, 'c': 20, 'd': 20, 'e': 20, 'f': 20}
May I know which part of the codes I am wrong?
It's because total is set to the last value in your for v in dataset.values() loop. You should try
dict1={k: sum(v) for k,v in dataset.items()}
You are just storing the last total in your solution. Try doing this instead:
dataset = {
"a" : [3, 1, 7, 5, 9],
"b" : [4, 8, 7, 5, 3],
"c" : [3, 4, 1, 0, 0],
"d" : [0, 5, 1, 5, 5],
"e" : [3, 7, 5, 5, 1],
"f" : [3, 6, 9, 2, 0],
}
dict1 = {k: sum(v) for k, v in dataset.items()}
print(dict1)
'total' changes after each iteration. Every time you go through a value in your dictionary and take the sum, you get a new total. So when the loop ends, total is the sum of the last list in your dictionary.
You are making each key in your dictionary have the value of the total for the last list. Instead, you should assign the total for each key inside the loop you are calculating total.
try this one.
dataset = {
"a" : [3, 1, 7, 5, 9],
"b" : [4, 8, 7, 5, 3],
"c" : [3, 4, 1, 0, 0],
"d" : [0, 5, 1, 5, 5],
"e" : [3, 7, 5, 5, 1],
"f" : [3, 6, 9, 2, 0],
}
result = {}
for (k, v) in dataset.items():
result[k] = sum(v)
print (result)
output:
{'a': 25, 'c': 8, 'b': 27, 'e': 21, 'd': 16, 'f': 20}
You are setting total once for every list of values in dataset, but by the time you use dictionary comprehension to create your dict1, you're only using the last calculated value of total, which happens to be 20. (Dicts are not ordered, so total could have ended with any of your sum values, depending on which random order the values were visited in.)
Instead, you can do all of this in one line, using a handy function called items(), which turns a dict into a list of pairs (i.e.: 2-tuples) of corresponding keys and values. So you can rewrite your dict1 code like this:
dict1 = {k: sum(v) for (k, v) in dataset.items()}
When you run the following part of your code, the total is updated for every value in the dataset dictionary, and then the total is updated to the sum of the last element of the dictionary, i.e. [3, 6, 9, 2, 0], hence total=20
for v in dataset.values():
total = (sum(v))
print(total)
And then when you do dict1 = {k:total for k in dataset}, all values of dict1 are 20`.
Two ways to simplify this.
Iterate through the input dictionary and update the output dictionary at the same time, this is most efficient
total = []
dict1 = {}
for k, v in dataset.items():
total = sum(v)
dict1[k] = total
print(dict1)
#{'a': 25, 'b': 27, 'c': 8, 'd': 16, 'e': 21, 'f': 20}
Iterate through the values, and then make a list of all the sums, and then iterate through the keys, and make the output dictionary. Note that this is grossly inefficient, but can be treated as the intermediate step from going to the code you currently have, to the first approach.
total = []
dict1 = {}
#Create the list of sums
for v in dataset.values():
total.append(sum(v))
idx = 0
#Use that list of sums to create the output dictionary
for k in dataset.keys():
dict1[k] = total[idx]
idx+=1
print(dict1)
#{'a': 25, 'b': 27, 'c': 8, 'd': 16, 'e': 21, 'f': 20}
I have a dictionary dictM in the form of
dictM={movieID:[rating1,rating2,rating3,rating4]}
Key is a movieID and rating1, rating2, rating3, rating4 are its values. There are several movieID's with ratings. I want to move certain movieID's along with ratings to a new dicitonary if a movieID has a certain number of ratings.
What I'm doing is :
for movie in dictM.keys():
if len(dictM[movie])>=5:
dF[movie]=d[movie]
But I'm not getting the desired result. Does someone know a solution for this?
You can use dictionary comprehension, as follows:
>>> dictM = {1: [1, 2, 3, 4], 2: [1, 2, 3]}
>>> {k: v for (k, v) in dictM.items() if len(v) ==4}
{1: [1, 2, 3, 4]}
You can try this using simple dictionary comprhension:
dictM={3:[4, 3, 2, 5, 1]}
new_dict = {a:b for a, b in dictM.items() if len(b) >= 5}
One reason why your code above may not be producing any results is first, you have not defined dF and the the length of the only value in dictM is equal to 4, but you want 5 or above, as shown in the if statement in your code.
You don't delete the entries, you could do it like this:
dictM = {1: [1, 2, 3],
2: [1, 2, 3, 4, 5],
3: [1, 2, 3, 4, 5, 6, 7],
4: [1]}
dF = {}
for movieID in list(dictM):
if len(dictM[movieID]) >= 5:
dF[movieID] = dictM[movieID] # put the movie + rating in the new dict
del dictM[movieID] # remove the movie from the old dict
The result looks like this:
>>> dictM
{1: [1, 2, 3], 4: [1]}
>>> dF
{2: [1, 2, 3, 4, 5], 3: [1, 2, 3, 4, 5, 6, 7]}