Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I made a successful attempt on the TestDome.com Fileowners problem and wanted to see if anyone had suggestions to simplify my answer. The online IDE uses Python 3.5.1. If you are trying to do the problem yourself and are just looking for an answer, here's one. I am by know means a Python expert so this took me quite a while to produce with lots of tinkering. Any comments at all would be helpful even if its about syntax or general cleanliness. THANKS!
Implement a group_by_owners function that:
Accepts a dictionary containing the file owner name for each file name.
Returns a dictionary containing a list of file names for each owner name, in any order.
For example, for dictionary {'Input.txt': 'Randy', 'Code.py': 'Stan', 'Output.txt': 'Randy'} the group_by_owners function should return {'Randy': ['Input.txt', 'Output.txt'], 'Stan': ['Code.py']}.
class FileOwners:
#staticmethod
def group_by_owners(files):
val = (list(files.values())) #get values from dict
val = set(val) #make values a set to remove duplicates
val = list(val) #make set a list so we can work with it
keyst = (list(files.keys())) #get keys from dict
result = {} #creat empty dict for output
for i in range(len(val)): #loop over values(owners)
for j in range(len(keyst)): #loop over keys(files)
if val[i]==list(files.values())[j]: #boolean to pick out files for current owner loop
dummylist = [keyst[j]] #make string pulled from dict a list so we can add it to the output in the correct format
if val[i] in result: #if the owner is already in the output add the new file to the existing dictionary entry
result[val[i]].append(keyst[j]) #add the new file
else: #if the owner is NOT already in the output make a new entry
result[val[i]] = dummylist #make a new entry
return result
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(FileOwners.group_by_owners(files))
Output:
{'Stan': ['Code.py'], 'Randy': ['Output.txt', 'Input.txt']}
Holly molly, that's a lot of code for something so simple:
def group_by_owners(files):
result = {}
for file, owner in files.items(): # use files.iteritems() on Python 2.x
result[owner] = result.get(owner, []) + [file] # you can use setdefault(), too
return result
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(group_by_owners(files))
# {'Stan': ['Code.py'], 'Randy': ['Output.txt', 'Input.txt']}
You can simplify it even further by using collections.defaultdict for result and initializing all its keys to list - then you don't even need to do the acrobatics of creating a new list if it's not already there before appending to it.
I personally found the upvoted answer hard to understand and some others a bit bulky. Here is my version:
def group_by_owners(files):
ownerdict = {}
for key, value in files.items():
if value in ownerdict:
ownerdict[value].append(key)
else:
ownerdict[value] = [key]
return ownerdict
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(group_by_owners(files))
This worked for me. I believe this would be more efficient and simpler one.
# Input dictionary.
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
# Function to group the files.
def group_by_owners(files):
# Dictionary object to hold the result.
result = {}
for key, value in files.items():
if value not in result.keys():
# Insert the values into the resulting dictionary
# by interchanging the key, values.
result[value] = [key]
else:
# Append the othet file name if the owner is same.
result[value].append(key)
return result
print(group_by_owners(files))
Here is the output:
{'Randy': ['Input.txt', 'Output.txt'], 'Stan': ['Code.py']}
I just started learning and I am a noob at python too but used 2.7. So spare me the parentheses for prints.
I like your idea of dummy list and append. Something similar but may be a little cleaner:
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
owners=[]
filenames=files.keys()
for key in files:
if files[key] not in owners:
owners.append(files[key])
print owners
print filenames
result={}
for i in owners:
resultvalues=[]
for key in files:
if files[key]==i:
resultvalues.append(key)
print resultvalues
result[i]=resultvalues
print result
here I mentioning easily understandable solution,
owner = []
for i in dict1.keys():
if j not in owner:
owner.append(j)
results = {}
for i in owner:
result = []
for j in dict1.keys():
if dict1.get(j) == i:
result.append(j)
results[i] = result
print results
def group_by_owners(files):
values = []
dic = {}
for k,v in files.items():
values.append(v)
s_values = set(values)
l_values = list(s_values)
for i in l_values:
keys=[]
for k,v in files.items():
if v == i:
keys.append(k)
dic[i]=keys
return dic
You all seems better I took 3.5 hours to get answer with lot of try and error as am new to python and weak in thinking focused, thanks to #zwer for teaching something new.
dic={'apple':['green','red'], 'power': ['voltage'],'banana': ['green','red'],'current':['voltage'],'grass':['green'],'tiger':['lion']}
i = 0
adic = {}
while i < len(dic):
key = list(dic)[i]
for key2 in list(dic):
if key2 != key:
j = 0
while j < len(dic[key]):
if dic[key][j] in dic[key2]:
color = dic[key][j]
if dic[key][j] in adic:
if key not in adic[color]:
adic[dic[key][j]].append(key)
else:
mdic = {dic[key][j]: [key]}
adic.update(mdic)
else:
if dic[key][j] not in adic:
mdic = {dic[key][j]: [key]}
adic.update(mdic)
j = j + 1
i = i + 1
print(adic)
class FileOwners:
def group_by_owners(files):
temp=[]
for i in files:
if files[i] not in temp:
temp.append (files[i])
result={}
for j in temp:
temp1=[]
for i in files:
if files[i]==j:
temp1.append(i)
result[j]=temp1
return (result)
files = {'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'}
print(FileOwners.group_by_owners(files))
You have to iterate Dictionary into Dictionary and compare values and append keys in a new list. Take output in a new Dictionary.
class FileOwners:
#staticmethod
def group_by_owners(files):
new_dic = {}
for key,val in files.items():
key_list = []
for k,v in files.items():
if v == val:
#print(v)
key_list.append(k)
new_dic[v]= key_list
return new_dic
#print(new_dic)
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(FileOwners.group_by_owners(files))
I made a dict of owners and their associated list of filenames. To do that i firstly created the dictionary with the values of the passed dictionary files as keys and empty list as values. Then looped through files and appended the empty list with the keys of files
def group_by_owners(files):
return_dict = {}
owner_files = files.keys()
for f in owner_files:
return_dict[files[f]] = []
for f, n in files.items():
return_dict[n].append(f)
return return_dict
I started learning Python yesterday and came across this question on testdome. Here's my answer :
def group_by_owners(files):
f = files.values()
s = set(f)
newdict={}
fileOwners = list(s)
for owner in fileOwners:
l=[]
for file in files:
if owner == files[file]:
l.append(file)
newdict[owner]=l
return newdict
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(group_by_owners(files))
This is some complex code to understand.
but is one of the solutions.
files={
'input.txt':'randy',
'output.txt':'randy',
'code.py':'stan'
}
k=files.keys()
newfiles={value:key for key,value in files.items()}
emptylist=[]
for key in k:
if key not in newfiles.values():
missfile=key
valuetoadd=files[missfile]
emptylist.append(newfiles[valuetoadd])
emptylist.append(missfile)
newfiles[valuetoadd]=emptylist
print(newfiles)
Here is my answer with defaultdict:
from collections import defaultdict
d = defaultdict(list)
def group_by_owners(files):
for k,v in files.items():
d[v].append(k)
return dict(d.items())
if __name__ == "__main__":
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(group_by_owners(files))
Related
can anyone please help me to find the solution
I am having a JSON file like below
{
"Parent1": ["Child1", "Child2","Child5"],
"Parent2": ["Child3", "Child4","Child5"]
}
expectation: Python code to find the parent name using child name
User input: Child1
Expected output : Parent1
OR
User input: Child5
Expected output : Parent1,Parent2
This is an apporach you can use
choice = input("Enter search string ")
ans = []
for i,j in data.items():
if choice in j:
ans.append(i)
ans will now contain the keys you need as a list
You should read the json file and then loop over the dictionary to find matching for the given input
def find_key_name_by_value(json_input, key_to_find):
result = []
for key, value in input.items():
if key_to_find in value:
result.append(key)
return result
json_input = {
"Parent1": ["Child1", "Child2","Child5"],
"Parent2": ["Child3", "Child4","Child5"]
}
result = find_key_name_by_value(json_input, "Child4")
print(result)
I had a task to flatten nested dict, which was easy. This is my code for that:
class Simple:
def __init__(self):
self.store_data = {}
def extract_data(self, config):
for key in config:
if isinstance(config[key], dict):
self.extract_data(config[key])
else:
self.store_data[{key}] = config[key]
return self.store_data
This was my intput:
input = {
'k1_lv1': {
'k1_lv2': 'v1_lv2', 'k2_lv2': 'v2_lv2'},
'k2_lv1': 'v1_lv1',
'k3_lv1': {
'k1_lv2': 'v1_lv2', 'k2_lv2': 'v2_vl2'},
'k4_lv1': 'v1_lv1',
}
and this was my output (imagine that the keys are unique):
output = {
'k1_lv2': 'v1_lv2', 'k2_lv2': 'v2_lv2',
'k2_lv1': 'v1_lv1',
'k1_lv2': 'v1_lv2', 'k2_lv2': 'v2_vl2',
'k4_lv1': 'v1_lv1'
}
but now my task has been changed and my output has to become like this:
output = {
'k1_lv1_k1_lv2': 'v1_lv2',
'k1_lv1_k2_lv2': 'v2_lv2',
'k2_lv1': 'v1_lv1',
'k3_lv1_k1_lv2': 'v1_lv2',
'k3_lv1_k2_lv2': 'v2_vl2',
'k4_lv1': 'v1_lv1'
}
so I have to not only flatten the nested dict, but have to save the keys of nested dicts.
I tried to achieve that output but I am failing.
You can use recursion for the task:
dct = {
"k1_lv1": {"k1_lv2": "v1_lv2", "k2_lv2": "v2_lv2"},
"k2_lv1": "v1_lv1",
"k3_lv1": {"k1_lv2": "v1_lv2", "k2_lv2": "v2_vl2"},
"k4_lv1": "v1_lv1",
}
def flatten(d, path=""):
if isinstance(d, dict):
for k, v in d.items():
yield from flatten(v, (path + "_" + k).strip("_"))
else:
yield (path, d)
out = dict(flatten(dct))
print(out)
Prints:
{
"k1_lv1_k1_lv2": "v1_lv2",
"k1_lv1_k2_lv2": "v2_lv2",
"k2_lv1": "v1_lv1",
"k3_lv1_k1_lv2": "v1_lv2",
"k3_lv1_k2_lv2": "v2_vl2",
"k4_lv1": "v1_lv1",
}
Why don't you loop through the keys using input.keys() and then stack keys using
output['{}_{}'.format(key_level1, key_level2]]= input['key_level1']['key_level2']
You might need to nest for loops and add a condition to test the depth of the keys in your dictionnary.
I am trying to create a nested dictionary, whereby the key to each nested dictionary is named from the value from a variable. My end result should look something like this:
data_dict = {
'jane': {'name': 'jane', 'email': 'jane#example.com'},
'jim': {'name': 'jim', 'email': 'jim#example.com'}
}
Here is what I am trying:
data_dict = {}
s = "jane"
data_dict[s][name] = 'jane'
To my surprise, this does not work. Is this possible?
You want something like:
data_dict = {}
s = "jane"
data_dict[s] = {}
data_dict[s]['name'] = s
That should work, though I would recommend instead of a nested dictionary that you use a dictionary of names to either namedtuples or instances of a class.
Try this:
data_dict = {}
s = ["jane", "jim"]
for name in s:
data_dict[name] = {}
data_dict[name]['name'] = name
data_dict[name]['email'] = name + '#example.com'
as #Milad in the comment mentioned, you first need to initialize s as empty dictionary first
data={}
data['Tom']={}
data['Tom']['name'] = 'Tom Marvolo Riddle'
data['Tom']['email'] = 'iamlordvoldermort.com'
For existing dictionaries you can do dict[key] = value although if there is no dict that would raise an error. I think this is the code you want to have:
data_dict = {}
s = "jane"
data_dict[s] = {"name": s, "email": f"{s}#example.com"}
print(data_dict)
I just realized when I got a notification about this question:
data_dict = defaultdict(dict)
data_dict["jane"]["name"] = "jane"
Would be a better answer I think.
Given the following data received from a web form:
for key in request.form.keys():
print key, request.form.getlist(key)
group_name [u'myGroup']
category [u'social group']
creation_date [u'03/07/2013']
notes [u'Here are some notes about the group']
members[0][name] [u'Adam']
members[0][location] [u'London']
members[0][dob] [u'01/01/1981']
members[1][name] [u'Bruce']
members[1][location] [u'Cardiff']
members[1][dob] [u'02/02/1982']
How can I turn it into a dictionary like this? It's eventually going to be used as JSON but as JSON and dictionaries are easily interchanged my goal is just to get to the following structure.
event = {
group_name : 'myGroup',
notes : 'Here are some notes about the group,
category : 'social group',
creation_date : '03/07/2013',
members : [
{
name : 'Adam',
location : 'London',
dob : '01/01/1981'
}
{
name : 'Bruce',
location : 'Cardiff',
dob : '02/02/1982'
}
]
}
Here's what I have managed so far. Using the following list comprehension I can easily make sense of the ordinary fields:
event = [ (key, request.form.getlist(key)[0]) for key in request.form.keys() if key[0:7] != "catches" ]
but I'm struggling with the members list. There can be any number of members. I think I need to separately create a list for them and add that to a dictionary with the non-iterative records. I can get the member data like this:
tmp_members = [(key, request.form.getlist(key)) for key in request.form.keys() if key[0:7]=="members"]
Then I can pull out the list index and field name:
member_arr = []
members_orig = [ (key, request.form.getlist(key)[0]) for key in request.form.keys() if key[0:7] ==
"members" ]
for i in members_orig:
p1 = i[0].index('[')
p2 = i[0].index(']')
members_index = i[0][p1+1:p2]
p1 = i[0].rfind('[')
members_field = i[0][p1+1:-1]
But how do I add this to my data structure. The following won't work because I could be trying to process members[1][name] before members[0][name].
members_arr[int(members_index)] = {members_field : i[1]}
This seems very convoluted. Is there a simper way of doing this, and if not how can I get this working?
You could store the data in a dictionary and then use the json library.
import json
json_data = json.dumps(dict)
print(json_data)
This will print a json string.
Check out the json library here
Yes, convert it to a dictionary, then use json.dumps(), with some optional parameters, to print out the JSON in the format you need:
eventdict = {
'group_name': 'myGroup',
'notes': 'Here are some notes about the group',
'category': 'social group',
'creation_date': '03/07/2013',
'members': [
{'name': 'Adam',
'location': 'London',
'dob': '01/01/1981'},
{'name': 'Bruce',
'location': 'Cardiff',
'dob': '02/02/1982'}
]
}
import json
print json.dumps(eventdict, indent=4)
The order of the key:value pairs is not always consistent, but if you're just looking for pretty-looking JSON that can be parsed by a script, while remaining human-readable, this should work. You can also sort the keys alphabetically, using:
print json.dumps(eventdict, indent=4, sort_keys=True)
The following python functions can be used to create a nested dictionary from the flat dictionary. Just pass in the html form output to decode().
def get_key_name(str):
first_pos = str.find('[')
return str[:first_pos]
def get_subkey_name(str):
'''Used with lists of dictionaries only'''
first_pos = str.rfind('[')
last_pos = str.rfind(']')
return str[first_pos:last_pos+1]
def get_key_index(str):
first_pos = str.find('[')
last_pos = str.find(']')
return str[first_pos:last_pos+1]
def decode(idic):
odic = {} # Initialise an empty dictionary
# Scan all the top level keys
for key in idic:
# Nested entries have [] in their key
if '[' in key and ']' in key:
if key.rfind('[') == key.find('[') and key.rfind(']') == key.find(']'):
print key, 'is a nested list'
key_name = get_key_name(key)
key_index = int(get_key_index(key).replace('[','',1).replace(']','',1))
# Append can't be used because we may not get the list in the correct order.
try:
odic[key_name][key_index] = idic[key][0]
except KeyError: # List doesn't yet exist
odic[key_name] = [None] * (key_index + 1)
odic[key_name][key_index] = idic[key][0]
except IndexError: # List is too short
odic[key_name] = odic[key_name] + ([None] * (key_index - len(odic[key_name]) + 1 ))
# TO DO: This could be a function
odic[key_name][key_index] = idic[key][0]
else:
key_name = get_key_name(key)
key_index = int(get_key_index(key).replace('[','',1).replace(']','',1))
subkey_name = get_subkey_name(key).replace('[','',1).replace(']','',1)
try:
odic[key_name][key_index][subkey_name] = idic[key][0]
except KeyError: # Dictionary doesn't yet exist
print "KeyError"
# The dictionaries must not be bound to the same object
odic[key_name] = [{} for _ in range(key_index+1)]
odic[key_name][key_index][subkey_name] = idic[key][0]
except IndexError: # List is too short
# The dictionaries must not be bound to the same object
odic[key_name] = odic[key_name] + [{} for _ in range(key_index - len(odic[key_name]) + 1)]
odic[key_name][key_index][subkey_name] = idic[key][0]
else:
# This can be added to the output dictionary directly
print key, 'is a simple key value pair'
odic[key] = idic[key][0]
return odic
I'm using Yahoo Placemaker API which gives different structure of json depending on input.
Simple json file looks like this:
{
'document':{
'itemDetails':{
'id'='0'
'prop1':'1',
'prop2':'2'
}
'other':{
'propA':'A',
'propB':'B'
}
}
}
When I want to access itemDetails I simply write json_file['document']['itemDetails'].
But when I get more complicated response, such as
{
'document':{
'1':{
'itemDetails':{
'id'='1'
'prop1':'1',
'prop2':'2'
}
},
'0':{
'itemDetails':{
'id'='0'
'prop1':'1',
'prop2':'2'
},
'2':{
'itemDetails':{
'id'='1'
'prop1':'1',
'prop2':'2'
}
'other':{
'propA':'A',
'propB':'B'
}
}
}
the solution obviously does not work.
I use id, prop1 and prop2 to create objects.
What would be the best approach to automatically access itemDetails in the second case without writing json_file['document']['0']['itemDetails'] ?
If I understand correctly, you want to loop through all of json_file['document']['0']['itemDetails'], json_file['document']['1']['itemDetails'], ...
If that's the case, then:
item_details = {}
for key, value in json_file['document']:
item_details[key] = value['itemDetails']
Or, a one-liner:
item_details = {k: v['itemDetails'] for k, v in json_file['document']}
Then, you would access them as item_details['0'], item_details['1'], ...
Note: You can suppress the single quotes around 0 and 1, by using int(key) or int(k).
Edit:
If you want to access both cases seamlessly (whether there is one result or many), you could check:
if 'itemDetails' in json_file['document']:
item_details = {'0': json_file['document']['itemDetails']}
else:
item_details = {k: v['itemDetails'] for k, v in json_file['document'] if k != 'other'}
Then loop through the item_details dict.