3

How to sort my dictionary using this condition in python.

I have a Nested Dictionary which is describe below.

my_dict={
         "Moli": {"Price": 226, "Quantity": 300, "PreOrder": "Yes", "PostOrder": "No", "Dif": 36},
         "Anna": {"Price": 530, "Quantity": 154, "PreOrder": "No", "PostOrder": "Yes", "Dif": 26},
         "Bob": {"Price": 250, "Quantity": 100, "PreOrder": "No", "PostOrder": "No", "Dif": 46},
         "Annie": {"Price": 656, "Quantity": 96, "PreOrder": "Yes", "PostOrder": "No", "Dif": 55},
         "Calley": {"Price": 546, "Quantity": 76, "PreOrder": "No", "PostOrder": "Yes", "Dif": 35}
        }

I want to apply a condition on this nested dictionary. The condition is_

Sort the items where ("PreOrder"== "Yes" or "PostOrder"== "Yes") and show those item in descending order using "Quantity" value

Something like this.

my_dict2 = {("PreOrder"== "Yes" or "PostOrder"== "Yes") i[0]: i[1] for i in sorted(my_dict.items(), key=lambda x: x[1]["Quantity"], reverse=True)}

I know it's a wrong code.

expected output_

my_dict2={
         "Moli": {"Price": 226, "Quantity": 300, "PreOrder": "Yes", "PostOrder": "No", "Dif": 36},
         "Anna": {"Price": 530, "Quantity": 154, "PreOrder": "No", "PostOrder": "Yes", "Dif": 26},
         "Annie": {"Price": 656, "Quantity": 96, "PreOrder": "Yes", "PostOrder": "No", "Dif": 55},
         "Calley": {"Price": 546, "Quantity": 76, "PreOrder": "No", "PostOrder": "Yes", "Dif": 35}
         }

I would be very grateful if you could help me

Shijith
  • 4,602
  • 2
  • 20
  • 34
ammely
  • 85
  • 1
  • 8
  • that first condition is for filtering, not sorting. Do you only want the items with `"PreOrder"== "Yes" or "PostOrder"== "Yes"`? – Chase Nov 02 '20 at 09:43
  • Why is the key `Bob` missing from your expected output? – Mayank Porwal Nov 02 '20 at 09:43
  • Because Bob's ("PreOrder"== "Yes" or "PostOrder"== "Yes") this condition is false. "PreOrder": "No", "PostOrder": "No" – ammely Nov 02 '20 at 09:47
  • and yes first check the condition then sorting in descending order using "Quantity" value – ammely Nov 02 '20 at 09:48
  • Can I write the code like this filtered = {i[0]: i[1] for i in sorted(my_dict.items(), key=lambda x: x[1]["Quantity"], reverse=True) if i[1]["True" not in my_dict[(list(my_dict.keys())[0])].values()]} – ammely Nov 02 '20 at 10:07

2 Answers2

2

This involves multiple steps as you describe. First, we need a dict with only the items that we want. This filters the dict.

filtered = {k: v for k, v in my_dict.items() if v['PreOrder'] == 'Yes' or v['PostOrder'] == 'Yes'}

Then you want to show the items in order. This implies a list, not a dictionary. So we'll make one with tuples from the original dict.

items = [(k, v) for k, v in filtered.items()]

Finally, we need to sort the items. As you've written already, sort accepts any arbitrary sorting method, so we can pass in a lambda function for that.

ordered = sorted(items, key=lambda i: i[1]['Quantity'], reversed=True)

In general, it is very helpful to think about your problems in minimal steps.

Felix
  • 2,548
  • 19
  • 48
  • 1
    you can do `sorted(filtered.items(), key=lambda i: i[1]['Quantity'])` btw – Chase Nov 02 '20 at 09:49
  • @Chase Good point! I would emphasize the need to understand the meaning of every step, but once you are comfortable, these kinds of shortcuts can be made. – Felix Nov 02 '20 at 09:50
  • Also, since, if i'm correct, version 3.6, dicts are sorted, so ending up with a dict instead of list is possible. – go2nirvana Nov 02 '20 at 09:55
  • But sir I getting output like this_ – ammely Nov 02 '20 at 09:56
  • @go2nirvana True, but I'm personally still uncomfortable with assuming it, because the data structure isn't built for that. For example when switching to other languages it would be easier to make the transition with the same concepts, not relying on an ordered dict. – Felix Nov 02 '20 at 09:58
  • my_dict2={ "Moli": {"Price": 226, "Quantity": 300, "PreOrder": "Yes", "PostOrder": "No", "Dif": 36}, "Anna": {"Price": 530, "Quantity": 154, "PreOrder": "No", "PostOrder": "Yes", "Dif": 26}, "Annie": {"Price": 656, "Quantity": 96, "PreOrder": "Yes", "PostOrder": "No", "Dif": 55}, "Calley": {"Price": 546, "Quantity": 76, "PreOrder": "No", "PostOrder": "Yes", "Dif": 35} } – ammely Nov 02 '20 at 10:04
  • Can I write the code like this filtered = {i[0]: i[1] for i in sorted(my_dict.items(), key=lambda x: x[1]["Quantity"], reverse=True) if i[1]["True" not in my_dict[(list(my_dict.keys())[0])].values()]} – ammely Nov 02 '20 at 10:07
  • @ammely Do you mean the reverse? My bad, I'll include it in the answer. With regards your other question, I don't really know what you mean. It could be better to ask another question for that. Also, tip: backticks for formatting `code`. – Felix Nov 02 '20 at 10:08
0

You can also do this using pandas library:

This saves a lot of lines of code and also reduces a lot of complexity.

Install pandas:

pip install pandas

Then, create a dataframe from my_dict:

In [229]: import pandas as pd

In [230]: df = pd.DataFrame(my_dict)

In [235]: df1 = df.T

In [244]: my_dict2 = df1[df1.PreOrder.eq('Yes') | df1.PostOrder.eq('Yes')].sort_values(by='Quantity', ascending=False).T.to_dict()

In [245]: my_dict2
Out[245]: 
{'Moli': {'Price': 226,
  'Quantity': 300,
  'PreOrder': 'Yes',
  'PostOrder': 'No',
  'Dif': 36},
 'Anna': {'Price': 530,
  'Quantity': 154,
  'PreOrder': 'No',
  'PostOrder': 'Yes',
  'Dif': 26},
 'Annie': {'Price': 656,
  'Quantity': 96,
  'PreOrder': 'Yes',
  'PostOrder': 'No',
  'Dif': 55},
 'Calley': {'Price': 546,
  'Quantity': 76,
  'PreOrder': 'No',
  'PostOrder': 'Yes',
  'Dif': 35}}
Mayank Porwal
  • 33,470
  • 8
  • 37
  • 58