I got a very difficult assignment as I am new to python, I hope you will be able to help me.
I wrote this code:
def hours_per_student(student_course,course_hours):
new={}
for key in student_course.keys():
for val in student_course.values():
for m in range(len(val)):
if not new.has_key(key):
new[key]=course_hours[val[m]]
else:
new[key]=new[key]+course_hours[val[m]]
return new
for these dictionaries:
student_course = {'rina' : ['math', 'python'], 'yossi' : ['chemistry', 'biology'], 'riki' : ['python']}
course_hours = {'math' : 4, 'python' : 4, 'chemistry' : 6, 'biology' : 5}
And I need to get this:
hours_per_student(student_course, course_hours)
to return this:
{'rina': 8, 'yossi': 11, 'riki': 4}
But I keep getting identical numbers for each key.
You shouldn't be iterating over .values() if you're already iterating over .keys(), just use the key to get the value. Or where you have for m in len(val), just do for m in val and then reference m instead of val[m](the naming here stinks but I discuss that later). Python is much better at iteration than that. For instance, instead of the line
for val in student_course.values():
you should try something like
for courses in student_course[key]:
for course in courses:
if key not in new:
new[key] = course_hours[course]
else:
new[key] += course_hours[course]
Naming your variables intelligently will make it easier for you to keep track of what's happening. For example, each value in student_course is a list of courses, so you should name it that, not something ambiguous like val. Similarly, each element in courses is the name of a course, so name it as such.
Here you go:
solution = {student: sum([hours.get(course, 0) for course in s_courses]) for student, s_courses in student_course.items()}
Here are the things I found lacking in your code:
When iterating over your students, you could have just created a key for each of them, and then add the hours per course.
Naming variables so you understand what they mean is confused, refrain from using new, key or val.
You don't have to use keys() function, iterating a dictionary using for key in dictionary works the same way.
Here's a fixed code snippet:
def hours_per_student(students, course_hours):
total_hours = {}
for student in students:
courses = students[student]
total_hours[student] = 0
for course in courses:
total_hours[student] += course_hours[course]
return total_hours
Related
I have seen similar questions. This one is the most similar that I've found:
Python converting a list into a dict with a value of 1 for each key
The difference is that I need the dict keys to be unique and ordered keyword arguments.
I am trying to feed the list of links I've generated through a scraper into a request command. I understand the request.get() function only takes a URL string or kwarg parameters - hence my need to pair the list of links with keyword arguments that are ordered.
terms = (input(str('type boolean HERE -->')))
zipcity = (input(str('type location HERE -->')))
search = driver.find_element_by_id('keywordsearch')
search.click()
search.send_keys('terms')
location = driver.find_element_by_id('WHERE')
location.click()
location.send_keys('zipcity')
clickSearch = driver.find_element_by_css_selector('#buttonsearch-button')
clickSearch.click()
time.sleep(5)
cv = []
cvDict = {}
bbb = driver.find_elements_by_class_name('user-name')
for plink in bbb:
cv.append(plink.find_element_by_css_selector('a').get_attribute('href'))
cvDict = {x: 1 for x in cv}
print(cvDict)
SOLVED: (for now). Somehow figured it out myself. That literally never happens. Lucky day I guess!
cvDict = {'one': cv[:1],
'tw': cv[:2],
'thr': cv[:3],
'fou': cv[:4],
'fiv': cv[:5],
'six': cv[:6],
'sev': cv[:7],
'eig': cv[:8],
'nin': cv[:9],
'ten': cv[:10],
'ele': cv[:11],
'twe': cv[:12],
'thi': cv[:13],
'fourteen': cv[:14],
'fifteen': cv[:15],
'sixteen': cv[:16],
'seventeen': cv[:17],
'eighteen': cv[:18],
'nineteen': cv[:19],
'twent': cv[:20],
}
I am trying to extract particular lines from txt output file. The lines I am interested in are few lines above and few below the key_string that I am using to search through the results. The key string is the same for each results.
fi = open('Inputfile.txt')
fo = open('Outputfile.txt', 'a')
lines = fi.readlines()
filtered_list=[]
for item in lines:
if item.startswith("key string"):
filtered_list.append(lines[lines.index(item)-2])
filtered_list.append(lines[lines.index(item)+6])
filtered_list.append(lines[lines.index(item)+10])
filtered_list.append(lines[lines.index(item)+11])
fo.writelines(filtered_list)
fi.close()
fo.close()
The output file contains the right lines for the first record, but multiplied for every record available. How can I update the indexing so it can read every individual record? I've tried to find the solution but as a novice programmer I was struggling to use enumerate() function or collections package.
First of all, it would probably help if you said what exactly goes wrong with your code (a stack trace, it doesn't work at all, etc). Anyway, here's some thoughts. You can try to divide your problem into subproblems to make it easier to work with. In this case, let's separate finding the relevant lines from collecting them.
First, let's find the indexes of all the relevant lines.
key = "key string"
relevant = []
for i, item in enumerate(lines):
if item.startswith(key):
relevant.append(item)
enumerate is actually quite simple. It takes a list, and returns a sequence of (index, item) pairs. So, enumerate(['a', 'b', 'c']) returns [(0, 'a'), (1, 'b'), (2, 'c')].
What I had written above can be achieved with a list comprehension:
relevant = [i for (i, item) in enumerate(lines) if item.startswith(key)]
So, we have the indexes of the relevant lines. Now, let's collected them. You are interested in the line 2 lines before it and 6 and 10 and 11 lines after it. If your first lines contains the key, then you have a problem – you don't really want lines[-1] – that's the last item! Also, you need to handle the situation in which your offset would take you past the end of the list: otherwise Python will raise an IndexError.
out = []
for r in relevant:
for offset in -2, 6, 10, 11:
index = r + offset
if 0 < index < len(lines):
out.append(lines[index])
You could also catch the IndexError, but that won't save us much typing, as we have to handle negative indexes anyway.
The whole program would look like this:
key = "key string"
with open('Inputfile.txt') as fi:
lines = fi.readlines()
relevant = [i for (i, item) in enumerate(lines) if item.startswith(key)]
out = []
for r in relevant:
for offset in -2, 6, 10, 11:
index = r + offset
if 0 < index < len(lines):
out.append(lines[index])
with open('Outputfile.txt', 'a') as fi:
fi.writelines(out)
To get rid of duplicates you can cast list to set; example:
x=['a','b','a']
y=set(x)
print(y)
will result in:
['a','b']
I've below lists,
lists=[ ['arya','egg','milk','butter','bread'],
['Jon','butter','pastrie','yogurt','beer'],
['bran','beer','milk','banana','apples'],]
Each list has values in which the first value is the name of a person and rest of all are some food items. I've a task where I've to create a dictionary with these food items as keys and the person as a value as shown below
dict = { 'egg' : set(['arya']),
'milk': set(['arya','bran']),
'butter' : set(['arya','jon']),
'bread' : set(['arya']),
'pastrie' : set(['jon']),
'milk' : set(['bran'])
} # few keys omitted
This is what I did and stopped, dont know how to proceed further,
food,person = [],[]
for i in lists:
food.append(i[1:])
person.append(i[0])
I was able to seperate the first value of each list and append it to a list
and same with food.
Dont know how to proceed further.
started learning python, Any input is highly helpful. kindly share one or two lines of explanation to enlighten this newbie !
Thank you so much.
Using dictionary method setdefault is helpful here.
You of course don't nee to set the slices to a variable, but it makes it easier to read.
d = {}
for l in lists:
name = l[0]
items = l[1:]
for item in items:
d.setdefault(item, set()).add(name)
Use a collections.defaultdict:
lists = [['arya', 'egg', 'milk', 'butter', 'bread'],
['Jon', 'butter', 'pastrie', 'yogurt', 'beer'],
['bran', 'beer', 'milk', 'banana', 'apples']]
from collections import defaultdict
d = defaultdict(set)
for sub in lists:
for v in sub[1:]:
d[v].add(sub[0])
print(d)
Output:
defaultdict(<class 'set'>,
{'bread': {'arya'}, 'yogurt': {'Jon'}, 'beer': {'Jon', 'bran'},
'banana': {'bran'}, 'butter': {'Jon', 'arya'}, 'milk': {'arya',
'bran'}, 'pastrie': {'Jon'}, 'egg': {'arya'}, 'apples': {'bran'}})
For python3 the syntax is a little nicer:
from collections import defaultdict
d = defaultdict(set)
for name, *rest in lists:
for v in rest:
d[v].add(name)
I'm trying to do two things. (1) display each element of an existing list, and (2) search a list to display all names that contain that element.
Here are some facts:
classes(hannes, [cs490, cs499, cs413]). % name has this list of classes
classes(tony, [ma330, ma211, ma250]).
classes(nicholas, [cs424, cs570, ma330]).
classes(pj, [ma211, ma250, ma285, cs424]).
classes(inga, [cs285, cs307, cs309]).
classes(christine, [ma285, ma211, ma330]).
classes(lisa, [cs424, cs413, cs490]).
classes(marty, [cs570, cs424]).
And, here is my rule so far:
taking(N,C) :- % student Name N is taking class C
classes(N,Cs),
[C|T] = Cs.
At the moment, I know this only takes the head of the list and displays it. I need to display each item of the list (one line at a time, if easy enough to do, but not important). But, I also need to be able to do it in reverse. If 1 course is queried (ma330), I want it to display all students that have that particular course.
Query example 1:
?- taking(nicholas, Classes).
Classes = [cs424, cs570, ma330] ;
OR
?- taking(nicholas, Classes).
Classes = cs424 ;
Classes = cs570 ;
Classes = ma330 ;
Query example 2:
?- taking(Names, ma330).
Names = tony ;
Names = nicholas ;
Names = christine ;
I'm going to keep searching for a resolution, but if anyone can help, it would be appreciated.
Thank you!!!
Think of that : C is member of Classes.
EDIT OK try this code :
taking(N,C) :- % student Name N is taking class C
classes(N,Cs),
member(C, Cs).
For example i have erlang record:
-record(state, {clients
}).
Can i make from clients field list?
That I could keep in client filed as in normal list? And how can i add some values in this list?
Thank you.
Maybe you mean something like:
-module(reclist).
-export([empty_state/0, some_state/0,
add_client/1, del_client/1,
get_clients/1]).
-record(state,
{
clients = [] ::[pos_integer()],
dbname ::char()
}).
empty_state() ->
#state{}.
some_state() ->
#state{
clients = [1,2,3],
dbname = "QA"}.
del_client(Client) ->
S = some_state(),
C = S#state.clients,
S#state{clients = lists:delete(Client, C)}.
add_client(Client) ->
S = some_state(),
C = S#state.clients,
S#state{clients = [Client|C]}.
get_clients(#state{clients = C, dbname = _D}) ->
C.
Test:
1> reclist:empty_state().
{state,[],undefined}
2> reclist:some_state().
{state,[1,2,3],"QA"}
3> reclist:add_client(4).
{state,[4,1,2,3],"QA"}
4> reclist:del_client(2).
{state,[1,3],"QA"}
::[pos_integer()] means that the type of the field is a list of positive integer values, starting from 1; it's the hint for the analysis tool dialyzer, when it performs type checking.
Erlang also allows you use pattern matching on records:
5> reclist:get_clients(reclist:some_state()).
[1,2,3]
Further reading:
Records
Types and Function Specifications
dialyzer(1)
#JUST MY correct OPINION's answer made me remember that I love how Haskell goes about getting the values of the fields in the data type.
Here's a definition of a data type, stolen from Learn You a Haskell for Great Good!, which leverages record syntax:
data Car = Car {company :: String
,model :: String
,year :: Int
} deriving (Show)
It creates functions company, model and year, that lookup fields in the data type. We first make a new car:
ghci> Car "Toyota" "Supra" 2005
Car {company = "Toyota", model = "Supra", year = 2005}
Or, using record syntax (the order of fields doesn't matter):
ghci> Car {model = "Supra", year = 2005, company = "Toyota"}
Car {company = "Toyota", model = "Supra", year = 2005}
ghci> let supra = Car {model = "Supra", year = 2005, company = "Toyota"}
ghci> year supra
2005
We can even use pattern matching:
ghci> let (Car {company = c, model = m, year = y}) = supra
ghci> "This " ++ c ++ " " ++ m ++ " was made in " ++ show y
"This Toyota Supra was made in 2005"
I remember there were attempts to implement something similar to Haskell's record syntax in Erlang, but not sure if they were successful.
Some posts, concerning these attempts:
In Response to "What Sucks About Erlang"
Geeking out with Lisp Flavoured Erlang. However I would ignore parameterized modules here.
It seems that LFE uses macros, which are similar to what provides Scheme (Racket, for instance), when you want to create a new value of some structure:
> (define-struct car (company model year))
> (define supra (make-car "Toyota" "Supra" 2005))
> (car-model supra)
"Supra"
I hope we'll have something close to Haskell record syntax in the future, that would be really practically useful and handy.
Yasir's answer is the correct one, but I'm going to show you WHY it works the way it works so you can understand records a bit better.
Records in Erlang are a hack (and a pretty ugly one). Using the record definition from Yasir's answer...
-record(state,
{
clients = [] ::[pos_integer()],
dbname ::char()
}).
...when you instantiate this with #state{} (as Yasir did in empty_state/0 function), what you really get back is this:
{state, [], undefined}
That is to say your "record" is just a tuple tagged with the name of the record (state in this case) followed by the record's contents. Inside BEAM itself there is no record. It's just another tuple with Erlang data types contained within it. This is the key to understanding how things work (and the limitations of records to boot).
Now when Yasir did this...
add_client(Client) ->
S = some_state(),
C = S#state.clients,
S#state{clients = [Client|C]}.
...the S#state.clients bit translates into code internally that looks like element(2,S). You're using, in other words, standard tuple manipulation functions. S#state.clients is just a symbolic way of saying the same thing, but in a way that lets you know what element 2 actually is. It's syntactic saccharine that's an improvement over keeping track of individual fields in your tuples in an error-prone way.
Now for that last S#state{clients = [Client|C]} bit, I'm not absolutely positive as to what code is generated behind the scenes, but it is likely just straightforward stuff that does the equivalent of {state, [Client|C], element(3,S)}. It:
tags a new tuple with the name of the record (provided as #state),
copies the elements from S (dictated by the S# portion),
except for the clients piece overridden by {clients = [Client|C]}.
All of this magic is done via a preprocessing hack behind the scenes.
Understanding how records work behind the scenes is beneficial both for understanding code written using records as well as for understanding how to use them yourself (not to mention understanding why things that seem to "make sense" don't work with records -- because they don't actually exist down in the abstract machine...yet).
If you are only adding or removing single items from the clients list in the state you could cut down on typing with a macro.
-record(state, {clients = [] }).
-define(AddClientToState(Client,State),
State#state{clients = lists:append([Client], State#state.clients) } ).
-define(RemoveClientFromState(Client,State),
State#state{clients = lists:delete(Client, State#state.clients) } ).
Here is a test escript that demonstrates:
#!/usr/bin/env escript
-record(state, {clients = [] }).
-define(AddClientToState(Client,State),
State#state{clients = lists:append([Client], State#state.clients)} ).
-define(RemoveClientFromState(Client,State),
State#state{clients = lists:delete(Client, State#state.clients)} ).
main(_) ->
%Start with a state with a empty list of clients.
State0 = #state{},
io:format("Empty State: ~p~n",[State0]),
%Add foo to the list
State1 = ?AddClientToState(foo,State0),
io:format("State after adding foo: ~p~n",[State1]),
%Add bar to the list.
State2 = ?AddClientToState(bar,State1),
io:format("State after adding bar: ~p~n",[State2]),
%Add baz to the list.
State3 = ?AddClientToState(baz,State2),
io:format("State after adding baz: ~p~n",[State3]),
%Remove bar from the list.
State4 = ?RemoveClientFromState(bar,State3),
io:format("State after removing bar: ~p~n",[State4]).
Result:
Empty State: {state,[]}
State after adding foo: {state,[foo]}
State after adding bar: {state,[bar,foo]}
State after adding baz: {state,[baz,bar,foo]}
State after removing bar: {state,[baz,foo]}