I have a list and a dictionary and I want to ultimately find a sum of the values in the two. For example, I want the code below to return :
{gold coin : 45, rope : 1, dagger : 6, ruby : 1}
First I right a function to turn the dragonLoot list into a dictionary and then I run a Counter to add the two dictionaries together. However, when I run the code I get the following:
{'ruby': 1, 'gold coin': 3, 'dagger': 1}
Counter({'gold coin': 42, 'dagger': 5, 'rope': 1})
For some reason it looks like the Counter is not recognizing the dictionary that I create from dragonLoot. Does anyone have any suggestions on what I am doing wrong? Thanks!
inv = {'gold coin' : 42, 'rope' : 1, 'dagger' : 5}
dragonLoot = ['gold coin','dagger','gold coin','gold coin','ruby']
def inventory(item):
count = {}
for x in range(len(item)):
count.setdefault(item[x],0)
count[item[x]] = count[item[x]] + 1
print(count)
inv2 = inventory(dragonLoot)
from collections import Counter
dicts = [inv,inv2]
c = Counter()
for d in dicts:
c.update(d)
print(c)
You don't need the inventory function: Counter will count the iterable for you. You can also use + with Counter. Combine these, and you can do quite simply
inv = Counter({'gold coin' : 42, 'rope' : 1, 'dagger' : 5})
dragonLoot = ['gold coin','dagger','gold coin','gold coin','ruby']
inv += Counter(dragonLoot)
After this is run, inv will be Counter({'gold coin': 45, 'dagger': 6, 'rope': 1, 'ruby': 1}), as desired.
You are not returning the count in your inventory method:
def inventory(item):
count = {}
for x in range(len(item)):
count.setdefault(item[x],0)
count[item[x]] = count[item[x]] + 1
print(count)
You are simply printing your inventory calculation. Change that print to a return, or add a return line after the print:
def inventory(item):
count = {}
for x in range(len(item)):
count.setdefault(item[x],0)
count[item[x]] = count[item[x]] + 1
print(count)
return count
Adding that to your code and running it, gives this output:
Counter({'gold coin': 45, 'dagger': 6, 'rope': 1, 'ruby': 1})
Alternatively, the implementation provided by #nneonneo is optimal.
Here is an other way to do it without the Counter:
dragonLoot = ['gold coin','dagger','gold coin','gold coin','ruby']
inv = {'gold coin' : 42, 'rope' : 1, 'dagger' : 5}
for i in dragonLoot:
inv[i] = inv.get(i, 0) +1
print (inv)
Output:
{'gold coin': 45, 'rope': 1, 'dagger': 6, 'ruby': 1}
Related
I'm working with Python 3.5.2 and I'm trying to get a dictionary ordered by key by using OrderedDict.
Here is what I'm trying:
import re
from collections import OrderedDict
BRACKETS_PATTERN = re.compile(r"(?P<info>.*)?\((?P<bracket_info>.*?)\)")
def transform_vertical(vertical, trans=True):
# elearning & Massive Online Open Courses (MOOCs) => ELEARNING_AND_MASSIVE_ONLINE_OPEN_COURSES
# Repair & Maintenance (SMB) => SMB_REPAIR_AND_MAINTENANCE
# Digital Advertising & Marketing/Untagged Agencies => DIGITAL_ADVERTISING_AND_MARKETING_OR_UNTAGGED_AGENCIES
if not trans:
return vertical
else:
v = vertical.replace(" & ", "_AND_").replace(", ", "_AND_").replace("/", "_OR_")
brackets_search_result = BRACKETS_PATTERN.search(v)
result = v
if brackets_search_result:
bracket_info = brackets_search_result.group("bracket_info")
info = brackets_search_result.group("info")
if bracket_info.upper() in ("SMB", "CBV"): # todo more prefix
result = bracket_info.upper() + "_" + info
else:
result = info
result = result.replace(" ", "_").upper().strip("_")
return result
VERTICAL_MAP = OrderedDict({
"GAMING": OrderedDict({
"MOBILE_GAMING": 1,
"AR_OR_VR_GAMING": 1,
"CONSOLE_AND_CROSS_PLATFORM_GAMING": 1,
"ESPORTS": 1,
"PC_GAMING": 1,
"REAL_MONEY_GAMING": 1,
}),
"TRAVEL": OrderedDict({
"AUTO_RENTAL": 1,
"RAILROADS": 1,
"HOTEL_AND_ACCOMODATION": 1,
"RIDE_SHARING_OR_TAXI_SERVICES": 1,
"TOURISM_AND_TRAVEL_SERVICES": 1,
"TOURISM_BOARD": 1,
"AIR": 1,
"TRAVEL_AGENCIES_AND_GUIDES_AND_OTAS": 1,
"CRUISES_AND_MARINE": 1,
})
})
s = list(VERTICAL_MAP[transform_vertical("Gaming")].keys())
print(s)
And I get non-ordered result like:
['REAL_MONEY_GAMING', 'AR_OR_VR_GAMING', 'MOBILE_GAMING', 'CONSOLE_AND_CROSS_PLATFORM_GAMING', 'ESPORTS', 'PC_GAMING']
Expected result:
[ 'MOBILE_GAMING', 'AR_OR_VR_GAMING','CONSOLE_AND_CROSS_PLATFORM_GAMING', 'ESPORTS', 'PC_GAMING', 'REAL_MONEY_GAMING']
What's wrong with my code and how to get an ordered result?
Dictionaries are not insertion ordered in Python 3.5.
You are instantiating the ordered dicts with arbitrarily ordered regular dicts. Construct each of the ordered dicts from a list of (key, value) tuples.
I am trying to return the weighted average of the student's grades based on the last definition. I have the dictionaries defined, but think my attempt to pull the numbers out is incorrect.
def Average(lst):
return sum(lst) / len(lst)
# Driver Code
lst = [1,2,3,4,5]
average = Average(lst)
print("Average of the list =", average)
def get_weighted_average(student):
return average('homework')*0.10 + average('quizzes')*0.30 + average('tests')*.60
#driver code
students = [steve, alice, tyler]
print(get_weighted_average('steve'))
How to get a weighted average out of a dictionary of grades above?
What is the primary source of your data? Text? Anyway, it looks like you have something like this in mind.
Imperative approach
1 - Your "database"
students_marks = {
'steve':{
'homework':[1,2,3,4,5],
'quizzes' :[5,4,3,2,1],
'tests' :[0,0,0,0,0],
},
'alice':{
'homework':[5,4,3,2,1],
'quizzes' :[0,0,0,0,0],
'tests' :[1,2,3,4,5],
},
}
use case:
>>> students_marks['steve']
{'homework': [1, 2, 3, 4, 5], 'quizzes': [5, 4, 3, 2, 1], 'tests': [0, 0, 0, 0, 0]}
>>> students_marks['steve']['homework']
[1, 2, 3, 4, 5]
2 - The definition of average and get_weighted_average
def average(lst):
return sum(lst)/len(lst) # Python3
#return sum(lst)/float(len(lst)) # Python2
def get_weighted_average(student_name):
student_marks = students_marks[student_name]
return round(
average(student_marks['homework'])*.1
+ average(student_marks['quizzes'])*.3
+ average(student_marks['tests'])*.6
, 2)
use case:
>>> get_weighted_average('steve')
1.2
>>> get_weighted_average('alice')
2.1
or using list
>>> students_names = ['steve', 'alice']
>>> [get_weighted_average(name) for name in students_names]
[1.2, 2.1]
or using dict
>>> {name:get_weighted_average(name) for name in students_names}
{'steve': 1.2, 'alice': 2.1}
Object-Oriented (OO) approach
All this being shown, what you want to do would probably be better done by programming in an OO manner. A quick example
class Student(object):
homeworks_weight = .1
quizzes_weight = .3
tests_weight = .6
def __init__(self, name, homeworks_marks, quizzes_marks, tests_marks):
self.name = name
self.homeworks_marks = homeworks_marks
self.quizzes_marks = quizzes_marks
self.tests_marks = tests_marks
#staticmethod
def average(marks):
return sum(marks)/len(marks)
def get_gpa(self, rd=2):
return round(
self.average(self.homeworks_marks)*self.homeworks_weight
+ average(self.quizzes_marks)*self.quizzes_weight
+ average(self.tests_marks)*self.tests_weight
, rd)
use case:
>>> steve = Student(
name = 'Steve',
homeworks_marks = [1,2,3,4,5],
quizzes_marks = [5,4,3,2,1],
tests_marks = [0,0,0,0,0]
)
>>> steve.get_gpa()
1.2
>>> steve.homeworks_marks
[1, 2, 3, 4, 5]
How can I change the keys of a dictionary of lists to display dates (outright) rather than datetime.date(2017, 1, 1) which is what they currently are formatted as?
Example of section of list:
{datetime.date(2017, 9, 7): [162.3, 163.24, 162.22, 163.18], datetime.date(2017, 7, 10): [160.44, 161.13, 160.44, 160.94],
I am rather new to python so any help would be much appreciated. Thanks.
call the strftime method for each datetime object:
import datetime
s = {datetime.date(2017, 9, 7): [162.3, 163.24, 162.22, 163.18], datetime.date(2017, 7, 10): [160.44, 161.13, 160.44, 160.94]}
new_s = {a.strftime("%Y-%m-%d"):b for a, b in s.items()}
Output:
{'2017-07-10': [160.44, 161.13, 160.44, 160.94], '2017-09-07': [162.3, 163.24, 162.22, 163.18]}
Try this:
import datetime
my_dict = {datetime.date(2017, 9, 7): [162.3, 163.24, 162.22, 163.18], datetime.date(2017, 7, 10): [160.44, 161.13, 160.44, 160.94]}
new_dict = {str(k): v for k,v in my_dict.items()}
Output:
{'2017-07-10': [160.44, 161.13, 160.44, 160.94],
'2017-09-07': [162.3, 163.24, 162.22, 163.18]}
Say I have a dictionary of:
lst = {'adore': 10, 'hate': 10, 'hello': 10, 'pigeon': 1, 'would': 5, 'elections': 5}
And I have a list of:
mylist = [['a new', 'party'], ['to', 'lol'], ['compete'], ['in', 'adore', 'the 2013'], ['federal', 'elections'], ['The Free', 'Voters'], ['leadership', 'declined to'], ['join forces', 'according to', 'a leaked'], ['email from', 'Bernd Lucke'], ['Advocating', 'adore'] ]
I want to be able to search the list for the keys in the dictionary. If a word in the list is a key, then to take the value of that key and add it to a counter. In the end, to have a total sum of all the values.
Is there a way to do this?
Like this?
lst = {'adore': 10, 'hate': 10, 'hello': 10, 'pigeon': 1, 'would': 5, 'elections': 5}
mylist = [['a new', 'party'], ['to', 'lol'], ['compete'], ['in', 'adore', 'the 2013'], ['federal', 'elections'], ['The Free', 'Voters'], ['leadership', 'declined to'], ['join forces', 'according to', 'a leaked'], ['email from', 'Bernd Lucke'], ['Advocating', 'adore']]
print([lst.get(i) for j in mylist for i in j if lst.get(i) != None])
print(sum([lst.get(i) for j in mylist for i in j if lst.get(i) != None]))
Output:
[10, 5, 10]
25
If you don't like them in one line:
total = []
for i in mylist:
for j in i:
if lst.get(i) != None:
total.append(lst.get(i))
print(sum(total))
Probably you can do this in a more pythonic way.
lst = {'adore': 10, 'hate': 10, 'hello': 10, 'pigeon': 1, 'would': 5}
counter = {'adore': 0, 'hate': 0, 'hello': 0, 'pigeon': 0, 'would': 0}
mylist = [['a new', 'party'], ['to', 'lol'], ['compete'], ['in', 'adore', 'the 2013'], ['federal', 'elections'], ['The Free', 'Voters'], ['leadership', 'declined to'], ['join forces', 'according to', 'a leaked'], ['email from', 'Bernd Lucke'], ['Advocating', 'adore'] ]
def func():
for key in lst.keys():
for item in mylist:
if key in item:
counter[key] = counter[key] + lst[key]
func()
print sum(counter.values())
I have a list of lists that looks like this
[['ip1',404],
['ip1',200],
['ip1',200],
['ip2',200],
['ip2',200],
['ip2',504]]
I need to make a dictionary that has counts of the status codes by ip address.
results = {'ip1':{404:1,200:2},'ip2':{200:2,504:1}}
The tools in collections make short work of this problem:
>>> from collections import defaultdict, Counter
>>> d = defaultdict(Counter)
>>> for ip, code in [['ip1',404], ['ip1',200], ['ip1',200],
['ip2',200], ['ip2',200], ['ip2',504]]:
d[ip][code] += 1
>>> dict(d)
{'ip2': Counter({200: 2, 504: 1}), 'ip1': Counter({200: 2, 404: 1})}
>>> from collections import defaultdict
>>> d = defaultdict(lambda: defaultdict(int))
>>> ips = [['ip1',404],['ip1',200],['ip1',200],['ip2',200],['ip2',200],['ip2',504]]
>>> for ip,num in ips:
d[ip][num] += 1
>>> d
defaultdict(<function <lambda> at 0x00000000035D6648>, {'ip2': defaultdict(<class 'int'>, {200: 2, 504: 1}), 'ip1': defaultdict(<class 'int'>, {200: 2, 404: 1})})
try this:
values = [['ip1',404],
['ip1',200],
['ip1',200],
['ip2',200],
['ip2',200],
['ip2',504]]
counts = {}
for value in values:
ip, status_code = value
if ip not in counts:
counts[ip] = {}
if status_code not in counts[ip]:
counts[ip][status_code] = 0
counts[ip][status_code] += 1
{'ip2': {200: 2, 504: 1}, 'ip1': {200: 2, 404: 1}}
it should work on virtually any python version.
>>> l
[['ip1', 404],
['ip1', 200],
['ip1', 200],
['ip2', 200],
['ip2', 200],
['ip2', 504]]
>>> {ip: {code: l.count([ip, code])
... for code in (p[1] for p in l if p[0]==ip)}
... for ip in (p[0] for p in l)}
{'ip1': {200: 2, 404: 1}, 'ip2': {200: 2, 504: 1}}
L = [[ip1,404], [ip1,200], [ip1,200], [ip2,200], [ip2,200], [ip2,504]]
D = {}
for entry in L:
ip = entry[0]
code = entry[1]
ip_entry = D.get(ip, {})
ip_entry[code] = ip_entry.get(code, 0) + 1
D[ip] = ip_entry