I've managed to figure out how to run a SQL query to display information. I need to keep the data in the same form as the db tables, so I think I should be using a dictionary. So far, my fields are ID and Name, my print looks like this:
[{'ID': '123', 'Name': 'ROBERTSON*ROBERT'}, {'ID': '456', 'Name': 'MICHAELS*MIKE'}, {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}, ...]
First, am I appropriately using dictionary?
Next, I need to split the Name field based on the * delimiter. For example:
Before:
{'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}
After:
{'ID': '789', 'LastName': 'KRISTENSEN', 'FirstName': 'KRISTEN'}
I've tested out a few things of code I've found but keep hitting roadblocks. I've used this to create my dictionary, I'm wondering if I include a split in this line to reduce a step?
query = [dict(zip(['ID', 'Name'],row)) for row in cursor.fetchall()]
Like so maybe:
query = [dict(zip(['ID', 'FirstName', 'LastName'], row[:1] + row[1].split('*'))) for row in cursor.fetchall()]
db_dict = {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}
name = db_dict['Name']
def split_name(name):
for index, char in enumerate(name):
if char == '*':
position = index
last_name = name[:position]
first_name = name[position + 1:]
return {'LastName':last_name, 'FirstName':first_name}
new_db_dict = {db_dict.keys()[0] : db_dict.values()[0]}
new_db_dict.update(split_name(name))
print new_db_dict
First, while your use of dictionaries is valid I recommend using namedtuples for representing fixed structures with named fields
from collections import namedtuple
# structure class factory
Person = namedtuple("Person", ("id", "name"))
people = [ Person('123', 'ROBERTSON*ROBERT'), Person('456','MICHAELS*MIKE'), Person('789', 'KRISTENSEN*KRISTEN')]
# different structure
PersonName = namedtuple("Person", ("id", "first", "last"))
# structure transformation
def person_to_personname(person):
"""Transform Person -> PersonName"""
names = person.name.split('*')
if len(names) < 2: # depends on your defaults
last = names[0]
first = ''
else: # assumes first field is last name
last, first = names[:2] # even if other names present, takes first two
return PersonName(person.id, first, last)
people_names = [person_to_personname(person) for person in people]
If all entries have a name split by an asterix
A solution in two steps. Once you've retrieved your current results :
a = [{'ID': '123', 'Name': 'ROBERTSON*ROBERT'}, {'ID': '456', 'Name': 'MICHAELS*MIKE'}, {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}]
result = [{'ID' : entry['ID'], 'LastName' : entry['Name'].split('*')[0], 'FirstName' : entry['Name'].split('*')[1]} for entry in a]
now if you print result :
[{'FirstName': 'ROBERT', 'ID': '123', 'LastName': 'ROBERTSON'},
{'FirstName': 'MIKE', 'ID': '456', 'LastName': 'MICHAELS'},
{'FirstName': 'KRISTEN', 'ID': '789', 'LastName': 'KRISTENSEN'}]
Otherwise (assuming that the field 'Name' is at least populated)
results = []
for entry in a:
name = entry['Name'].split('*')
result = dict(ID = entry['ID'], LastName = name[0])
if len(name) > 1:
result['FirstName'] = name[1]
results.append(result)
Related
I am working with django and got back a response that looks like this
Name,surname
AVA,AAJ
DAA2,ASA
EAA23,VVD
GAA43,DDA
AAA42,AAS
MAA21,JJ
produced by this code
#api_view(["POST"])
def testfunc(request):
if request.method == 'POST':
x = request.body.decode('utf-8')
print(x)
return JsonResponse(x,safe=False)
i want to place this into a dictionary with the first row being the key and the remaining rows being the values, so they can be further processed.
You need to first split the text in lines and then split words in each line.
Something like this:
lines = x.strip().split("\n")
keys = lines[0].split(",")
users_list = []
for line in lines[1:]:
d = dict()
for i, val in enumerate(line.strip().split(",")):
d[keys[i]] = val
users_list.append(d)
example output:
>>> print(users_list)
[{'Name': 'AVA', 'surname': 'AAJ'}, {'Name': 'DAA2', 'surname': 'ASA'}, {'Name': 'EAA23', 'surname': 'VVD'}, {'Name': 'GAA43', 'surname': 'DDA'}, {'Name': 'AAA42', 'surname': 'AAS'}, {'Name': 'MAA21', 'surname': 'JJ'}]
I am trying to write a simply query that will return all the attributes requested. The idea is to read the attributes names and return attribute information. It should start with the string 'select' and then followed by a list of the attributes the user wants to see
So, there is a small database consisting of dictionaries:
dsql_table =
[{'name': 'Jan', 'type': 'man', 'profession': 'Analyst'},
{'name': 'Max', 'type': 'man', 'profession': 'Doctor'}]
And the idea is to only implement the functionality (disregarding error handling):
try:
query = input('dsql> ')
while query != 'exit':
# I need to implement code over here
print ('Thank you!')
How can I do this without using classes? So if one input e.g. 'select name type', then it should return 'michiel man
Jan man'.
First you need to get the attribute names from the query, then it's quite simple.
dsql_table = [
{'name': 'Jan', 'type': 'man', 'profession': 'Analyst'},
{'name': 'Max', 'type': 'man', 'profession': 'Doctor'},
]
query = 'select name type'
# extract selected attributes from query
selected_attributes = query.split()[1:]
result = []
for record in dsql_table:
# iterate over selected attributes, store value if attribute exists
for attribute in selected_attributes:
if attribute in record:
result.append(record[attribute])
# now result is a list ['Jan', 'man', 'Max', 'man']
print(' '.join(result))
Alternatively, result can be populated using a list comprehesion:
result = [
record[attribute]
for record in dsql_table
for attribute in selected_attributes
if attribute in record
]
I wanna make a dictionary has name's key & data.In views.py I wrote
data_dict ={}
def try_to_int(arg):
try:
return int(arg)
except:
return arg
def main():
book4 = xlrd.open_workbook('./data/excel1.xlsx')
sheet4 = book4.sheet_by_index(0)
data_dict_origin = OrderedDict()
tag_list = sheet4.row_values(0)[1:]
for row_index in range(1, sheet4.nrows):
row = sheet4.row_values(row_index)[1:]
row = list(map(try_to_int, row))
data_dict_origin[row_index] = dict(zip(tag_list, row))
if data_dict_origin['name'] in data_dict:
data_dict[data_dict_origin['name']].update(data_dict_origin)
else:
data_dict[data_dict_origin['name']] = data_dict_origin
main()
When I printed out data_dict,it is
OrderedDict([(1, {'user_id': '100', 'group': 'A', 'name': 'Tom', 'dormitory': 'C'}), (2, {'user_id': '50', 'group': 'B', 'name': 'Blear', 'dormitory': 'E'})])
My ideal dictionary is
dicts = {
Tom: {
'user_id': '100',
'group': 'A',
'name': 'Tom',
'dormitory': 'C'
},
Blear: {
},
}
How should I fix this?What should I write it?
The code is using the wrong key in the dictionary. The keys are 1, 2, and do not have the name key. You can use this code instead:
for value in data_dict.values():
if value['name'] in data_dict:
data_dict[value['name']].update(value)
else:
data_dict[value['name']] = value
Your data_dict_origin has numbers as keys and dicts as values (which technically makes it a sparse array of dicts). The "name" key exists in those dicts, not in your data_dict.
def mergeDict(object):
dict1 = {}
for i in range(len(object)):
dict1.update({'id': object[i].id, 'name': object[i].name, 'age': object[i].age, 'location': object[i].location})
return dict1
merged_dict = mergeDict(details_sorted)
But this doesn't work.
I want to get something like this:
{1: {'id': 1, 'name': 'John', 'age': '25'; 'location': 'somewhere'},
2: {'id': 2, 'name': ......}}
It looks like the return statement is in the for loop, which means it will only ever return the update of the first dict.
You don't want to update the dict; you just want to insert a value on key i. Also, the return goes after the for, not in it. Here is a modified version:
def mergeDict(object):
dict1 = {}
for i in range(len(object)):
dict1[i] = {'id': object[i].id, 'name': object[i].name, 'age': object[i].age, 'location': object[i].location}
return dict1
merged_dict = mergeDict(details_sorted)
Your update version would have updated the id, name, age and location keys of dict1 -- and you don't want that. You want to update the id key of dict1 with another dictionary containing the keys id, name, age and location.
Do a bit of experiment.
def mergeDict(object):
dict1 = {}
dict1.update({'id': 'object[i].id', 'name': 'object[i].name', 'age': 'object[i].age', 'location': 'object[i].location'})
dict1.update({'id': 'object[j].id', 'name': 'object[j].name', 'age': 'object[j].age', 'location': 'object[j].location'})
return dict1
merged_dict = mergeDict(None)
print merged_dict
Output:
{'name': 'object[j].name', 'age': 'object[j].age', 'location': 'object[j].location', 'id': 'object[j].id'}
Errors:
Only last object values are retained as the keys are same for all objects. So the for loop has no effect.
It's like saying
x = {}
x['k'] = y
x['k'] = z
There is only one key - k and it's latest value is z
One-liner in Python 3.0:
merged_dict = {i: dict(id=o.id, name=o.name, age=o.age, location=o.location)
for i, o in enumerate(details_sorted)}
If the result keys are consecutive integers, why not a list instead of dict?
merged = [ dict(id=o.id, name=o.name, age=o.age, location=o.location)
for i, o in enumerate(details_sorted) ]
A list has the added benefit of preserving sort order.
In the following code below, how to retrieve the value of id,Id has multiple values in it.How to access the values of id and update it to result1
def parse_results ():
try:
xml = minidom.parseString(new_results)
for xmlchild in xmldoc.childNodes[0].childNodes :
result1 = {}
result1.update ({'firstname': xmlchild.getElementsByTagName("firstname")[0].childNodes[0].nodeValue})
result1.update ({'lastname': xmlchild.getElementsByTagName("lastname")[0].childNodes[0].nodeValue})
result1.update ({'address': address})
if xmlchild.getElementsByTagName("id")[0].childNodes[0].nodeValue:
logging.debug(xmlchild.getElementsByTagName("id")[0].childNodes[0].nodeValue.lower())
result1.update ({'id': id})
Edit:
xmlchild.getElementsByTagName("id")[0].childNodes[0].nodeValue -this statement gives an exception
Adding XML:
<info><firstname>firstname</firstname><lastname>lastname</lastname><id>2</id></info>
<info><firstname>firstname</firstname><lastname>lastname</lastname><id>3</id></info>
<info><firstname>firstname</firstname><lastname>lastname</lastname><id>4</id></info>
Why are you using minidom? It is really boring to use.
I suggest you move to element tree:
import xml.etree.ElementTree as et
d = et.fromstring('''
<doc>
<info><firstname>firstname</firstname><lastname>lastname</lastname><id>2</id></info>
<info><firstname>firstname</firstname><lastname>lastname</lastname><id>3</id></info>
<info><firstname>firstname</firstname><lastname>lastname</lastname><id>4</id></info>
</doc>
''')
result = [dict((el.tag, el.text) for el in info) for info in d.findall('info')]
print result
That prints:
[{'firstname': 'firstname', 'id': '2', 'lastname': 'lastname'},
{'firstname': 'firstname', 'id': '3', 'lastname': 'lastname'},
{'firstname': 'firstname', 'id': '4', 'lastname': 'lastname'}]