Using Python 3.3
Hi, I'm pretty new to programming/Python, so please don't go into too in-depth/complex methods of solving this problem.
I have a dictionary in which the keys are the person's name, and each of the key's values is a list of the names of the person's friends. For example:
friends_of_person = {'Albus': ['Ron', 'Hermione'], 'Harry': ['Ron', 'Hermione', 'Neville']}
This dictionary can be longer.
What my question is, how do I write a for loop or code that will loop through the values and compare each of the values to each of the values of another key's values. To make this clearer, let's use the above example. Albus is a friend to Harry, Ron, and Hermione. Harry is a friend to Ron and Hermione.
But I want to compare 'Ron' to the 'Ron', 'Hermione', and 'Neville' from the key Harry.
And then what I want is to see if 'Ron' is a friend of Harry. IF and ONLY if Ron is a friend of Harry, then I want to make 'Harry' as a potential friend of 'Albus'. The case applies to when comparing 'Hermione' to the 'Ron' and 'Hermione' from Harry's values. - this is like mutual friends.
The following is the code I've written, but it didn't seem to yield the correct answer.
friends_of_person = {'Albus': ['Ron', 'Hermione'], 'Harry': ['Ron', 'Hermione', 'Neville']}
for person in friends_of_person:
friends_list = friends_of_person[person]
for friend in friends_list:
recommendation = ''
for another_person in friends_of_person:
if friend in friends_of_person[another_person]:
recommendation = another_person
It doesn't seem correct. But if anyone can give me hints/tips to put me on the right direction, it'll be greatly appreciated!
Thank you in advance :)
Use set to check the intersection of people's friend list:
In [352]: lst1=friends_of_person['Albus']
In [353]: lst2=friends_of_person['Harry']
In [354]: lst1
Out[354]: ['Ron', 'Hermione']
In [355]: lst2
Out[355]: ['Ron', 'Hermione', 'Neville']
In [356]: set(lst1)&set(lst2)
Out[356]: set(['Hermione', 'Ron'])
If you want approach using only simple iterations and basic features, here you go:
for friend in friends_of_person['Albus']:
recommendation = []
for person, friends in friends_of_person.items():
if person == 'Albus':
continue # we don't need anyone who already is his friend
for potential in friends:
if potential in friends_of_person['Albus'] and potential not in recommendation:
recommendation.append(potential)
print(potential)
...:
Neville
PS. It's ugly, but that's what OP wanted...
#zhangxaochen's answer using sets is in my opinion the neatest. Nonetheless, if you want to use lists you could do something like:
friends = {'Albus': ['Ron', 'Hermione'], 'Harry': ['Ron', 'Hermione', 'Neville']}
def mutual_friends(a, b):
return [x for x in friends[a] if x in friends[b]]
Note that's re-coding set intersection (EDIT: if you have been instructed not to use set intersection then this solution is good since you code it yourself :)).
So
def recommendations(x):
result = []
for f in friends.keys():
if f != x and mutual_friends(x, f) > 1:
result.append(f)
return result
Basically, for a given person x, find all the people that have more than one mutual friend with them. You could change it to == 2 if you want exactly 2 mutual friends.
Related
Hey (Sorry bad english) so am going to try and make my question more clear. if i have a function let's say create_username_dict(name_list, username_list). which takes in two list's 1 being the name_list with names of people than the other list being usernames that is made out of the names of people. what i want to do is take does two list than convert them to a dictonary and set them together.
like this:
>>> name_list = ["Ola Nordmann", "Kari Olsen", "Roger Jensen"]
>>> username_list = ["alejon", "carli", "hanri"]
>>> create_username_dict(name_list, username_list)
{
"Albert Jones": "alejon",
"Carlos Lion": "carli",
"Hanna Richardo": "hanri"
}
i have tried look around on how to connect two different list in too one dictonary, but can't seem to find the right solution
If both lists are in matching order, i.e. the i-th element of one list corresponds to the i-th element of the other, then you can use this
D = dict(zip(name_list, username_list))
Use zip to pair the list.
d = {key: value for key,value in zip(name_list, username_list)}
print(d)
Output:
{'Ola Nordmann': 'alejon', 'Kari Olsen': 'carli', 'Roger Jensen': 'hanri'}
Considering both the list are same length and one to one mapping
name_list = ["Ola Nordmann", "Kari Olsen", "Roger Jensen"]
username_list = ["alejon", "carli", "hanri"]
result_stackoverflow = dict()
for index, name in enumerate(name_list):
result_stackoverflow[name] = username_list[index]
print(result_stackoverflow)
>>> {'Ola Nordmann': 'alejon', 'Kari Olsen': 'carli', 'Roger Jensen': 'hanri'}
Answer by #alex does the same but maybe too encapsulated for a beginner. So this is the verbose version.
tuplelist = [('John', 'David', 'Roger'), ('Linda', 'Jane', 'Siri')]
counter = 0
for x in tuplelist:
if counter != 0:
print(' likes ' + x[0])
print(x[0], end='')
counter += 1
I'm trying to find a good way to print the following using the list of tuples from the code above:
John likes Linda
David likes Jane
Roger likes Siri
The code above is my current attempt, which only prints "John likes Linda". I haven't found a solution to do this all at once. I could technically copy-paste the code twice and insert x[1] and x[2] in each block respectively. However, I've read that repetitious code is not good practice, so I was hoping some of you could help me in figuring out a more elegant solution.
Thank you very much for your help in advance
You can use build-in function zip
for man, woman in zip(*tuplelist):
print(man, 'likes', woman)
Although I think the answer by Relandom is the better and more pythonic appraoch, I would like to give you a second answer, pursuing the appraoch you tried (and might be easier to understand for beginners):
tuplelist = [('John', 'David', 'Roger'), ('Linda', 'Jane', 'Siri')]
counter = 0
for y in tuplelist[0]:
print(f'{y} likes {tuplelist[1][counter]}')
counter += 1
As you can see, we're still iterating over something. This time not the tuplelist, but the first tuple in this list (the male names). Sticking to your concept of a counter variable within the loop, we use this variable to access the second tuple (tuplelist[1]) in your list and get the respective value (=female name).
I have three lists, (1) treatments (2) medicine name and (3) medicine code symbol. I am trying to identify the respective medicine code symbol for each of 14,700 treatments. My current approach is to identify if any name in (2) is "in" (1), and then return the corresponding (3). However, I am returned an abitrary list (correct length) of medicine code symbols corresponding to the 14,700 treatments. Code for the method I've written is below:
codes = pandas.read_csv('Codes.csv', dtype=str)
codes_list = _codes.values.tolist()
names = pandas.read_csv('Names.csv', dtype=str)
names_list = names.values.tolist()
treatments = pandas.read_csv('Treatments.csv', dtype=str)
treatments_list = treatments.values.tolist()
matched_codes_list = range(len(treatments_list))
for i in range(len(treatments_list)):
for j in range(len(names_list)):
if names_list[j] in treatments_list[i]:
matched_codes_list[i]=codes_list_text[j]
print matched_codes_list
Any suggestions for where I am going wrong would be much appreciated!
I can't tell what you are expecting. You should replace the xxx_list code with examples instead, since you don't seem to have any problems with the csv reading.
Let's suppose you did that, and your result looks like this.
codes_list = ['shark', 'panda', 'horse']
names_list = ['fin', 'paw', 'hoof']
assert len(codes_list) == len(names_list)
treatments_list = ['tape up fin', 'reverse paw', 'stand on one hoof', 'pawn affinity maneuver', 'alert wing patrol']
it sounds like you are trying to determine the 'code' for each 'treatment', assuming that the number of codes and names are the same (and indicate some mapping). You plan to use the presence of the name to determine the code.
we can zip together the name and codes list to avoid using indexes there, and we can use iteration over the treatment list instead of indexes for pythonic readability
matched_codes_list = []
for treatment in treatment:
matched_codes = []
for name, code in zip(names_list, codes_list):
if name in treatment:
matched_codes.append(code)
matched_codes_list.append(matched_codes)
this would give something like
assert matched_codes_list == [
['shark'], # 'tape up fin'
['panda'], # 'reverse paw'
['horse'], # 'stand on one hoof'
['shark', 'panda', 'horse'], # 'pawn affinity maneuver'
[], # 'alert wing patrol'
]
note that the method used to do this is quite slow (and probably will give false positives, see 4th entry). You will traverse the text of all treatment descriptions once for each name/code pair.
You can use a dictionary like 'lookup = {name: code for name, code in zip(names_list, codes_list)}, or itertools.izip for minor gains. Otherwise something more clever might be needed, perhaps splitting treatments into a set containing words, or mapping words into multiple codes.
I've got the following which takes multiple lines of user input such as 'English Bob Luke' to store a Set in a Dictionary about which people speak which language. I've used a Dictionary to hold the multiple lines of input to create multiple Sets, but I now need to compare the difference between Sets to see if someone only speaks one language.
languages = {}
while True:
info = input('Line: ').split()
if info != []:
languages[info[0]] = set(info[1:])
else:
break
I can print the sets using the code below, but it doesn't seem to really get me anywhere!
for tongue in languages:
print(set(languages[tongue]))
Totally stuck - any help would be greatly appreciated!
UPDATE
Here in example of what I am trying to achieve:
Line: English Tim Nicky James John Ben
Line: German Nicky Tim Tara
Line: Mandarin Tim John
Line:
James is monolingual.
Tara is monolingual.
Ben is monolingual.
SOLUTION
Completely re-though my approach and ditched the Dictionary! :
english = input("Line: ").split()
en_speakers = set(english[1:len(english)])
multi_speakers = set()
while True:
language = input("Line: ").split()
lan_speakers = language[1:len(language)]
if language == []:
break
else:
multi_speakers |= set(lan_speakers)
monolinguals = en_speakers.difference(multi_speakers)
for person in monolinguals:
print(person, 'is monolingual.')
if multi_speakers == en_speakers:
print ('Everyone is multilingual!')
I'd reverse the order of keys and values in your dictionary, because it makes the problem so much easier. So rather than storing per language the different users that speak it, just create a per user profile of all the languages that person speaks:
from collections import defaultdict
user_langs = defaultdict(list)
while True:
info = map(lambda s: s.strip(), raw_input('Line: ').split())
if info:
for user in info[1:]:
user_langs[user].append(info[0])
else:
break
for user in user_langs:
if len(user_langs[user]) < 2:
print("{} is monolingual.".format(user))
languages[toungue] is already a set, you don't need to set(languages[touge]).
Also you don't need to loop the dictionary you can simply get those set from dictionary by lanuages.values().
Not entirely sure what you want to achieve here though. At a wild guess, you may want the unique value from the languages values?
You can achieve this by updating values to a new set:
Change this:
for tongue in languages:
print(set(languages[tongue]))
To this:
new_set = set()
for v in languages.values():
new_set.update(v)
new_set # dummy lanugages
{'English', 'Japanese', 'whatever', 'yeah'}
Updated
To achieve what you want, you can use Counter and return the key if value == 1.
A more detailed explanation is that, under a for/loop you are going to compare 1 set to another set. But what you actually need,is to compare all sets, so I choose to use c to update all individual set values under a for/loop, and afterward do whatever you want out from that c. I use Counter here as what you want to count if anyone has only got 1 language.
from collections import Counter
c = Counter()
for v in languages.values():
c.update(v)
for k,v in c.iteritems():
if v == 1:
print k, " is monolingual"
Ben is monolingual
James is monolingual
Tara is monolingual
The c looks like this:
c
Counter({'Tim': 3, 'Nicky': 2, 'John': 2, 'Ben': 1, 'James': 1, 'Tara': 1})
I have a list of names and addresses organized in the following format:
Mr and Mrs Jane Doe
Candycane Lane
Magic Meadows, SC
I have several blocks of data written like this, and I want to be able to alphabetize each block by the last name (Doe, in this case). After doing some digging, the best I can reckon is that I need to make a "List of lists" and then use the last name as a key by which to alphabetize the block. However, given by freshness to python and lack of Google skills, the closest I could find was this. I'm confused as to converting each block to a list and then slicing it; I can't seem to find a way to do this and still be able to alphabetize properly. Any and all guidance is greatly appreciated.
If I understood correctly, what you want basically is to sort values by "some computation done on the value", in this case the extracted last name.
For that, use the key keyword argument to .sort() or sorted():
def my_key_function(original_name):
## do something to extract the last name, for example:
try:
return original_name.split(',')[1].strip()
except IndexError:
return original_name
my_sorted_values = sorted(my_original_values, key=my_key_function)
The only requirement is that your "key" function is deterministic, i.e. always return the same output for each given input.
You might also want to sort by last name and then first name: in this case, just return a tuple (last, first): if last si the same for two given items, first will be used to further sort the two.
Update
For your specific case, this function should do the trick:
def my_key_function(original_name):
return original_name.splitlines()[0].split()[-1]
Assuming you already have the data in a list
l = ['Mr and Mrs Jane Smith\nCandycane Lane\nMagic Meadows, SC',
'Mr and Mrs Jane Doe\nCandycane Lane\nMagic Meadows, SC',
'Mr and Mrs Jane Atkins\nCandycane Lane\nMagic Meadows, SC']
You can specify the key to sort on.
l.sort(key=lambda x: x.split('\n')[0].split(' ')[-1])
In this case, get the last word (.split(' ')[-1]) on the first line (.split('\n')[0])
you want to make a new list where each entry is a tuple containing the sort key you want and the whole thing. Sort that list and then get the second component of each entry in the sort:
def get_sort_name (address):
name, address, city = address.split('\n')
return (name.split(' ')[-1] , address) # last item of first line & whole thing as tulle
keyed_list = map (get_sort_name, addresses)
keyed_list.sort()
sorted_addresses = [item[1] for item in keyed_list]
Thi could be more compact using lambdas of course but its better to be readable :)