how to print the list value of the nested dictionary - python

I have created the following dictionary:
Book_list={
'Fiction': {1001: ['Pride and Prejudice', 'available'],
1002: ['Fahrenheit 451', 'available']},
'Horror': {2001: ['House of leaves', 'available'],
2002: ['The Shinking', 'available']}}
now I want to store the status that is "available" in a variable with its key so that it can be used further for delete or update.
So the output I mean is like:
status={1001:available,1002:available,2001:available,2002:available}
Please help me by telling that how could I get this output.

One approach is to use a dictionary comprehension:
rs = {ii : status for category in Book_list.values() for ii, (name, status) in category.items() if status == "available"}
print(rs)
Output
{1001: 'available', 1002: 'available', 2001: 'available', 2002: 'available'}
The above is equivalent to the followings nested for loops:
for category in Book_list.values():
for ii, (name, status) in category.items():
if status == "available":
rs[ii] = status
For understanding the unpacking expressions such as:
# _, category
# ii, (name, status)
you could read this link. For a general introduction to Python's data structures I suggest reading the documentation.

def receive_available_books(Book_list):
status = {}
for cat in Book_list.values():
for code, book in cat.items():
status[code] = book[1]
return status
Output:
{1001: 'available', 1002: 'available', 2001: 'available', 2002: 'available'}

Using Python 3.10's structural pattern matching, maybe not super appropriate/helpful for this, but I just wanted to try it :-)
rs = {}
for category in Book_list.values():
for item in category.items():
match item:
case ii, [_, 'available' as status]:
rs[ii] = status
(code adapted from Dani's)

With this code you get almost exactly the output you want:
d={}
for a in Book_list.values():
for x,y in a.items():
d[x]=y[1]
print("status=", d)
You could also, of course, assign d to your a status variable.
This code just creates first an empty d as dict and then fills it with data and finally prints it. To fill d with data, a, x and y take different values while walking (iterating) over your object:
a: For example {1001: ['Pride and Prejudice', 'available'], 1002: ['Fahrenheit 451', 'available']}
x: For example 1001
y: For example ['Pride and Prejudice', 'available']
y[1] would then be 'available'

Related

Populate dictionary from MySQL python

I am pulling data from a MySQL db which comes in as a list.
'''
my_cursor.execute(sql_str)
my_results = my_cursor.fetchall()
print(my_results)
'''
OUTPUT
[('Allen, Jamie', 2), ('Anderson, Abbie', 1391), ('Anderson, Marcie', 1380), etc.,etc.
Instead of a list, I want to populate a dictionary.
'''
my_cursor.execute(sql_str)
my_result = {}
my_result = [{'Name': row[0], 'ID': row[1]} for row in my_cursor.fetchall()]
print(my_result)
'''
OUTPUT
[{'Name': 'Allen, Jamie', 'ID': 2}, {'Name': 'Anderson, Abbie', 'ID': 1391}, etc.
As you can see I am getting a list of directories not a directory. I really would appreciate your help.
Thanks,
John
You can convert the list to a dictionary like this:
L = [('Allen, Jamie', 2), ('Anderson, Abbie', 1391), ('Anderson, Marcie', 1380)]
D = dict(L)
print(D)
Now the dictionary D looks like this:
{'Allen, Jamie': 2, 'Anderson, Abbie': 1391, 'Anderson, Marcie': 1380}
You're using a list comprehension, so you're getting a list:
[{'Name': row[0], 'ID': row[1]} for row in my_cursor.fetchall()]
if you want a dictionary, use a dictionary comprehension instead:
$ python3 ./t.py
{'Dan': 1, 'John': 2}
data = [
[ "Dan", 1 ],
[ "John", 2 ]
]
print({row[0]: row[1] for row in data})
You could do as follows:
my_cursor.execute(sql_str)
my_result = {}
for x, y in a:
my_result[x] = y
print(my_result)
Depending on what library you're using for SQL, you may actually just be able to pass dictionary = True as an argument when creating your cursor object - I know this at least exists in mysql-connector-python.
my_cursor = conn.cursor(dictionary = True)
You don't say what MySQL package you're using. If it's mysql-connector-python, you can use my_cursor.description or my_cursor.column_names:
colnames = my_cursor.column_names
# Alternate for older library versions: colnames = [desc[0] for desc in my_cursor.description]
my_results = [dict(zip(colnames,record)) for record in my_results]

Sort a list of dictionaries by multiple keys/values, where the order of the values should be specific

I have a list of dictionaries and want each item to be sorted by a specific property values.
The list:
[
{'name':'alpha', status='run'},
{'name':'alpha', status='in'},
{'name':'alpha-32', status='in'},
{'name':'beta', status='out'}
{'name':'gama', status='par'}
{'name':'gama', status='in'}
{'name':'aeta', status='run'}
{'name':'aeta', status='unknown'}
{'pname': 'boc', status='run'}
]
I know I can do:
newlist = sorted(init_list, key=lambda k: (k['name'], k['status'])
but there two more conditions:
If the key name is no present in a dict, for the name to be used the value corresponding to pname key.
the status order to be ['out', 'in', 'par', 'run']
if the status value doesn't correspond with what is in the list, ignore it - see unknown;
The result should be:
[
{'name':'aeta', status='unknown'}
{'name':'aeta', status='run'}
{'name':'alpha', status='in'},
{'name':'alpha', status='run'},
{'name':'alpha-32', status='in'},
{'name':'beta', status='out'},
{'pname': 'boc', status='run'}
{'name':'gama', status='in'},
{'name':'gama', status='par'}
]
Use
from itertools import count
# Use count() instead of range(4) so that we
# don't need to worry about the length of the status list.
newlist = sorted(init_list,
key=lambda k: (k.get('name', k.get('pname')),
dict(zip(['out', 'in', 'par', 'run'], count())
).get(k['status'], -1)
)
)
If k['name'] doesn't exits, fall back to k['pname'] (or None if that doesn't exist). Likewise, if there is no known integer for the given status, default to -1.
I deliberately put this all in one logical line to demonstrate that at this point, you may want to just define the key function using a def statement.
def list_order(k):
name_to_use = k.get('name')
if name_to_use is None:
name_to_use = k['pname'] # Here, just assume pname is available
# Explicit definition; you might still write
# status_orders = dict(zip(['out', ...], count())),
# or better yet a dict comprehension like
# { status: rank for rank, status in enumerate(['out', ...]) }
status_orders = {
'out': 0,
'in': 1,
'par': 2,
'run': 3
}
status_to_use = status_orders.get(k['status'], -1)
return name_to_use, status_to_use
newlist = sorted(init_list, key=list_order)
The first condition is simple, you get default the first value of the ordering tuple to pname, i.e.
lambda k: (k.get('name', k.get('pname')), k['status'])
For the second and third rule I would define an order dict for statuses
status_order = {key: i for i, key in enumerate(['out', 'in', 'par', 'run'])}
and then use it in key-function
lambda k: (k.get('name', k.get('pname')), status_order.get(k['status']))
I haven't tested it, so it might need some tweaking

Getting associated values from Python dictionary that is using lists

Ok, so I am working on an application that can go through a number of different database objects, compare the string and return the associated id, first name and last name. I currently have it to where I am building a list of tuples and then populating a dictionary with the key and values(using a list). What I want to do next is find the Max percentage and then return the associated fist and last name from the dictionary. I know the description is a little confusing so please look at the below examples and code:
# My Dictionary:
{'percent': [51.9, 52.3, 81.8, 21.0], 'first_name': ['Bob', 'Bill', 'Matt', 'John'], 'last_name': ['Smith', 'Allen', 'Naran', 'Jacobs']}
# I would want this to be returned:
percent = 81.8 (Max percentage match)
first_name = 'Matt' (First name associated with the max percentage match)
last_name = 'Naran' (Last name associated with the max percentage match)
# Code so Far:
compare_list = []
compare_dict = {}
# Builds my list of Tuples
compare_list.append(tuple(("percent", percentage)))
compare_list.append(tuple(("first_name", first_name)))
compare_list.append(tuple(("last_name", last_name)))
# Builds my Dictionary
for x, y in compare_list:
compare_dict.setdefault(x, []).append(y)
Not sure where to go to return the first and last name associated with the Max percentage.
I really appreciate any and all help that you provide!
I hope this will help you:
data = {'percent': [51.9, 52.3, 81.8, 21.0], 'first_name': ['Bob', 'Bill', 'Matt', 'John'], 'last_name': ['Smith', 'Allen', 'Naran', 'Jacobs']}
percentage_list = data['percent']
percentage = max(percentage_list)
max_index = percentage_list.index(percentage)
first_name = data['first_name'][max_index]
last_name = data['last_name'][max_index]
# Code so Far:
compare_list = []
compare_dict = {}
# Builds my list of Tuples
compare_list.append(tuple(("percent", percentage)))
compare_list.append(tuple(("first_name", first_name)))
compare_list.append(tuple(("last_name", last_name)))
# Builds my Dictionary
for x, y in compare_list:
compare_dict.setdefault(x, []).append(y)
print compare_dict

Python 3.4 list to do different tasks

I have this list:
list1 = [
'aapl':'apple',
'tgt':'target',
'nke':'nike',
'mcd':'Mc Donald',
'googl':'google',
'yhoo':'yahoo',
'rl':'Polo Ralph lauren'
]
I wish to execute this
q = 0
while q < len(list1):
code_to_be_executed
q = q+1
But only for the 1st part (aapl,tgt,nke,mdc,rl,yhoo,etc) and the the 2nd part (the company name as google, yahoo , polo ralph lauren, etc ) to be printed in something like this : nke = nike to the user
The problem is it will perform the q task to everything even for the company name which is not what I want) I know I could seperate the abreviations and the company name in two different list but how could I print it like the nke = Nike comp. ? thank you very much
What I believe you are trying to do is a basic printing of a key/value data structure (called a dict in Python):
Example:
data = {
'aapl': 'apple', 'tgt': 'target', 'nke': 'nike', 'mcd': 'Mc Donald',
'googl': 'google', 'yhoo': 'yahoo', 'rl': 'Polo Ralph lauren'
}
for k, v in data.items():
print("{0:s}={1:s}".format(k, v))
Which outputs:
$ python app.py
nke=nike
tgt=target
aapl=apple
mcd=Mc Donald
rl=Polo Ralph lauren
yhoo=yahoo
googl=google
Update: If you still want to do this with a while loop with a q variant then your data structure will have to be a "list of tuples" -- Where each "tuple" is a key/value pair. e.g: [(1, 2), (3, 4)]
Example: (based on your code more or less)
data = [
('aapl', 'apple'),
('tgt', 'target'),
('nke', 'nike'),
('mcd', 'Mc Donald'),
('googl', 'google'),
('yhoo', 'yahoo'),
('rl', 'Polo Ralph lauren)')
]
q = 0 # counter
while q < len(data):
k, v = data[q] # assign and unpack each tuple (key, value)
print("{0:s}={1:s}".format(k, v))
q += 1
NB: This data structure is mostly the same except that you loose the benefits of being able to do O(1) lookups. Dictionaries/Mappings are more suited to this kind of data structure especially i you intend to perform lookups base don keys.

Sort list of dictionaries by value, regardless of keyname in python

I have a list of single entry dictionaries. Each dictionary has only 1 key and 1 value. I'd like to sort the list of dictionaries by these values REGARDLESS of the keyname! The key names are both the same and different from dictionary to dictionary.
All of the online examples I have seen assume the same key name across dictionaries. These type of examples have not worked for me because they assume the same key value:
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])
In my example, I need to compare the values regardless of whether the key is bob or sarah; and order the list of dictionaries. Here's an example list of dictionaries:
Times = [{"Bob":14.05}, {"Tim":15.09}, {"Tim":17.01}, {"Bob":16.81}, {"Sarah":15.08}]
desired output:
[{"Bob":14.05}, {"Sarah":15.08}, {"Tim":15.09}, {"Bob":16.81}, {"Tim":1701}]
times = [{"Bob":14.05},{"Tim":15.09},{"Tim":17.01},{"Bob":16.81},{"Sarah":15.08}]
print sorted(times, key=lambda k: k.values())
Output
[{'Bob': 14.05},{'Sarah': 15.08}, {'Tim': 15.09}, {'Bob': 16.81}, {'Tim': 17.01}]
If there are multiple values in the values list and if you want to consider only the elements at particular index, then you can do
print sorted(times, key=lambda k: k.values()[0])
What about:
newlist = sorted(Times, key=lambda k: k.values()[0])
It keys off the first (only) of the dictionary's .values()
#thefourtheye - your answer is quite nice.
Want to highlight a subtle and IMO interesting thing for folks new to python. Consider this tweak to thefourtheye's answer:
times = [{"Bob":14.05},{"Tim":15.09},{"Tim":17.01},{"Bob":16.81},{"Sarah":15.08}]
print sorted(times, key=lambda k: k.itervalues().next())
Which yields the same result:
[{'Bob': 14.05}, {'Sarah': 15.08}, {'Tim': 15.09}, {'Bob': 16.81}, {'Tim': 17.01}]
The tweak avoids the creation of an intermediate and unnecessary array. By using the iterator "itervalues()" and then getting just the first value (via .next()) the sort method just compares the raw value, without the array.
Let's look at performance:
test_cases = [
[],
[{"Bob":14.05}],
[{"Bob":14.05},{"Tim":15.09},{"Tim":17.01},{"Bob":16.81},{"Sarah":15.08}],
[dict(zip((str(x) for x in xrange(50)), random.sample(xrange(1000), 50)))] # 50 dict's in a list
]
print "perf test"
for test_case in test_cases:
print test_case
print "k.values() :", timeit.repeat(
"sorted(test_case, key=lambda k: k.values())",
"from __main__ import test_case",
)
print "k.itervalues().next():", timeit.repeat(
"sorted(test_case, key=lambda k: k.itervalues().next())",
"from __main__ import test_case",
)
print
results:
[]
k.values() : [0.7124178409576416, 0.7222259044647217, 0.7217190265655518]
k.itervalues().next(): [0.7274281978607178, 0.7140758037567139, 0.7135159969329834]
[{'Bob': 14.05}]
k.values() : [1.3001079559326172, 1.395097017288208, 1.314589023590088]
k.itervalues().next(): [1.2579071521759033, 1.2594029903411865, 1.2587871551513672]
[{'Bob': 14.05}, {'Tim': 15.09}, {'Tim': 17.01}, {'Bob': 16.81}, {'Sarah': 15.08}]
k.values() : [3.1186227798461914, 3.107577085494995, 3.1108040809631348]
k.itervalues().next(): [2.8267030715942383, 2.9143049716949463, 2.8211638927459717]
[{'42': 771, '48': 129, '43': 619, '49': 450, --- SNIP --- , '33': 162, '32': 764}]
k.values() : [1.5659689903259277, 1.6058270931243896, 1.5724899768829346]
k.itervalues().next(): [1.29836106300354, 1.2615361213684082, 1.267350196838379]
Mind you, perf will often not matter, but given that the 2 solutions are similar in terms of readabilty, expressiveness, I think it's good to understand the later solution, and build habits in those terms.

Categories