Reputation: 594
Despite the fact that I have seen a lot of answers about sorting a dictionary of a dictionary I was not able to adjust the solution to my problem.
Here is the structure of my dictionary:
OrderedDict([('2018-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 8}), ('2017-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 804,'ALFAMINO 400 GR.': 4, 'Forticare Orange/Lemon 4 X125ml': 15})])
The outer dictionary has as key a date in format year-month The outer dictionary has as value a dictionary in format {'name of product: quantity}
The inner dictionary has as key the name of the product The inner dictionary has as value the quantity(of the product)
My aim is to sort my outer dictionary based on the latest date(the newest to be first) and my inner dictionary based on the name of the product alphabetically.
In other words:
OrderedDict([('2018-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 8}),('2017-11',{'ALFAMINO 400 GR.': 4,'Forticare Orange/Lemon 4 X125ml': 15,'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 804})])
First goes the date 2018-11, is "newest" than 2017-11 and in inner dictionaries if I have more than one records as the dictionary with key 2017-11, first goes the ALFAMINO (starts with A), then the Forticare (starts with F) and so on..
Here is my code:
def warehouse_pending_products(request):
template_name= 'warehouse/warehouse_pending_products.html'
pendingOrdersResult={}
pendingOrdersList=Order.objects.filter(finished=0)
for order in pendingOrdersList:
orderYear=order.invoice_date.year
orderMonth=order.invoice_date.month
orderDate=str(orderYear)+'-'+str(orderMonth)
orderProductsWithoutSerials=ProductSerialNumbers.objects.filter(snumber__isnull=True).filter(order=order.id)#order_by('product__name')
if orderDate in pendingOrdersResult:
for op in orderProductsWithoutSerials:
p_name=op.product.name.encode("utf-8")
if p_name in pendingOrdersResult[orderDate]:
pendingOrdersResult[orderDate][p_name]+=1
else:
pendingOrdersResult[orderDate][p_name]=1
else:
if orderProductsWithoutSerials:
pendingOrdersResult[orderDate]={}
for op in orderProductsWithoutSerials:
p_name=op.product.name.encode("utf-8")
if p_name in pendingOrdersResult[orderDate]:
pendingOrdersResult[orderDate][p_name]+=1
else:
pendingOrdersResult[orderDate][p_name]=1
result = collections.OrderedDict(sorted(pendingOrdersResult.iteritems(), key=lambda (k, v): (pendingOrdersResult[k])))
My dictionary is the pendingOrdersResult.
The result = collections.OrderedDict(sorted(pendingOrdersResult.iteritems(), key=lambda (k, v): (pendingOrdersResult[k])))
gives wrong result.
Upvotes: 0
Views: 107
Reputation: 824
Try the following (tested with python 3.7.1):
import collections
raw = dict([('2018-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 8}), ('2017-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 804,'ALFAMINO 400 GR.': 4, 'Forticare Orange/Lemon 4 X125ml': 15})])
data = {key : collections.OrderedDict(sorted(value.items(), key=lambda entry: entry[0])) for key, value in raw.items()}
result = collections.OrderedDict(sorted(data.items(), key = lambda entry: entry[0]))
print(result)
EDIT: with a function to avoid the "c&p" code:
import collections
def sort_dict(unsorted):
return collections.OrderedDict(sorted(unsorted.items(), key=lambda entry: entry[0]))
raw = dict([('2018-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 8}), ('2017-11', {'NEOCATE JUNIOR WITHOUT FLAVOUR 400 gr.': 804,'ALFAMINO 400 GR.': 4, 'Forticare Orange/Lemon 4 X125ml': 15})])
result = sort_dict({key : sort_dict(value) for key, value in raw.items()})
print(result)
Upvotes: 1
Reputation: 11484
It sounds like you need to call the sorted
function on each of the "inner" dictionaries individually, as well as on the "outer" dictionary. You would also need to cast your inner dictionaries to have the OrderedDict
type for them to be sortable. Here's what I could come up with, but there might be shorter/more idiomatic ways to do this:
# Sort the outer dictionary by key from high to low
OrderedDict(sorted(d.items(), key=lambda t: t[0], reverse=True))
# Sort the inner dictionaries by key
for item in d.items():
d[item[0]] = OrderedDict(sorted(item[1].items(), key=lambda x: x[0]))
Upvotes: 2