Sick Gaming
[Tut] Python – How to Sort a List of Dictionaries? - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Programming (https://www.sickgaming.net/forum-76.html)
+--- Forum: Python (https://www.sickgaming.net/forum-83.html)
+--- Thread: [Tut] Python – How to Sort a List of Dictionaries? (/thread-94373.html)



[Tut] Python – How to Sort a List of Dictionaries? - xSicKxBot - 04-02-2020

Python – How to Sort a List of Dictionaries?

<div><p>In this article, you’ll learn the ins and outs of the sorting function in Python. In particular, you’re going to learn <strong>how to sort a list of dictionaries</strong> in all possible variations. [<a rel="noreferrer noopener" href="https://wiki.python.org/moin/SortingListsOfDictionaries" target="_blank">1</a>] So let’s get started!</p>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio">
<div class="wp-block-embed__wrapper">
<div class="ast-oembed-container"><iframe title="Python – How to Sort a List of Dictionaries?" width="1400" height="788" src="https://www.youtube.com/embed/aYYvCvMv7vQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</figure>
<p><strong>How to Sort a List of Dictionaries …</strong></p>
<h2>… By Value?</h2>
<p><strong>Problem</strong>: Given a list of dictionaries. Each dictionary consists of multiple (key, value) pairs. You want to sort them by value of a particular dictionary key (<em>attribute</em>). How do you sort this dictionary?</p>
<p><strong>Minimal Example</strong>: Consider the following example where you want to sort a list of salary dictionaries by value of the key <code>'Alice'</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">salaries = [{'Alice': 100000, 'Bob': 24000}, {'Alice': 121000, 'Bob': 48000}, {'Alice': 12000, 'Bob': 66000}] sorted_salaries = # ... Sorting Magic Here ... print(sorted_salaries)</pre>
<p>The output should look like this where the salary of Alice determines the order of the dictionaries:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'Alice': 12000, 'Bob': 66000},
{'Alice': 100000, 'Bob': 24000},
{'Alice': 121000, 'Bob': 48000}]</pre>
<p><strong>Solution</strong>: You have two main ways to do this—both are based on defining the key function of Python’s sorting methods. The key function maps each list element (in our case a dictionary) to a single value that can be used as the basis of comparison.</p>
<ul>
<li>Use a lambda function as key function to sort the list of dictionaries.</li>
<li>Use the itemgetter function as key function to sort the list of dictionaries.</li>
</ul>
<p>Here’s the code of the first option using a lambda function that returns the value of the key <code>'Alice'</code> from each dictionary:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Create the dictionary of Bob's and Alice's salary data
salaries = [{'Alice': 100000, 'Bob': 24000}, {'Alice': 121000, 'Bob': 48000}, {'Alice': 12000, 'Bob': 66000}] # Use the sorted() function with key argument to create a new dic.
# Each dictionary list element is "reduced" to the value stored for key 'Alice'
sorted_salaries = sorted(salaries, key=lambda d: d['Alice']) # Print everything to the shell
print(sorted_salaries)</pre>
<p>The output is the sorted dictionary. Note that the first dictionary has the smallest salary of Alice and the third dictionary has the largest salary of Alice.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'Alice': 12000, 'Bob': 66000}, {'Alice': 100000, 'Bob': 24000}, {'Alice': 121000, 'Bob': 48000}]</pre>
<p><strong>Try It Yourself:</strong></p>
<p> <iframe height="800px" width="100%" src="https://repl.it/@finxter/dictionarylistof?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> </p>
<p>You’ll learn about the second way below (where you use the <code>itemgetter</code> function from the <code>operator</code> module).</p>
<p><strong>Related articles on the Finxter blog:</strong></p>
<ul>
<li><a rel="noreferrer noopener" href="https://blog.finxter.com/python-list-sort/" target="_blank">Sorting Lists in Python</a></li>
<li><a rel="noreferrer noopener" href="https://blog.finxter.com/a-simple-introduction-of-the-lambda-function-in-python/" target="_blank">Lambda Functions</a></li>
<li><a rel="noreferrer noopener" href="https://blog.finxter.com/python-dictionary/" target="_blank">Dictionarie</a><a href="https://blog.finxter.com/python-dictionary/" target="_blank" rel="noreferrer noopener">s</a></li>
</ul>
<h2>… Using Itemgetter?</h2>
<p><strong>Same Problem</strong>: Given a list of dictionaries. Each dictionary consists of multiple (key, value) pairs. How to sort them by value of a particular dictionary key (<em>attribute</em>)?</p>
<p><strong>Minimal Example</strong>: Consider again the following example where you want to sort a list of salary dictionaries by value of the key <code>'Alice'</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">salaries = [{'Alice': 100000, 'Bob': 24000}, {'Alice': 121000, 'Bob': 48000}, {'Alice': 12000, 'Bob': 66000}] sorted_salaries = # ... Sorting Magic Here ... print(sorted_salaries)</pre>
<p>The output should look like this where the salary of Alice determines the order of the dictionaries:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'Alice': 12000, 'Bob': 66000},
{'Alice': 100000, 'Bob': 24000},
{'Alice': 121000, 'Bob': 48000}]</pre>
<p><strong>Solution</strong>: Again, you’re going to define a key function. But instead of creating it yourself with the <code>lambda</code> keyword, you’re going to use an existing one. In particular, you’ll use the <code>itemgetter</code> function from the <code>operator</code> module to sort the list of dictionaries.</p>
<p>Here’s the code of the first option using a lambda function that returns the value of the key <code>'Alice'</code> from each dictionary:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Import the itemgetter function from the operator module
from operator import itemgetter # Create the dictionary of Bob's and Alice's salary data
salaries = [{'Alice': 100000, 'Bob': 24000}, {'Alice': 121000, 'Bob': 48000}, {'Alice': 12000, 'Bob': 66000}] # Use the sorted() function with key argument to create a new dic.
# Each dictionary list element is "reduced" to the value stored for key 'Alice'
sorted_salaries = sorted(salaries, key=itemgetter('Alice')) # Print everything to the shell
print(sorted_salaries)
</pre>
<p>The output is the sorted dictionary. Note that the first dictionary has the smallest salary of Alice and the third dictionary has the largest salary of Alice.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'Alice': 12000, 'Bob': 66000}, {'Alice': 100000, 'Bob': 24000}, {'Alice': 121000, 'Bob': 48000}]</pre>
<p>Now, you know how to sort a list of dictionaries by value. But what if you want to sort by key?</p>
<h2>… By Key?</h2>
<p><strong>Problem</strong>: Given a list of dictionaries. Each dictionary consists of multiple (key, value) pairs. How to sort them by a particular key (<em>attribute</em>)?</p>
<p><strong>Solution</strong>: It doesn’t make sense. If you assume that all dictionaries have that same particular key, you cannot really sort because all dictionaries have the same key. If there’s no tie-breaker, it’s impossible to do. But even if there’s a tie-breaker (e.g. the value associated to the key), it doesn’t make sense because you could have sorted by value in the first place.</p>
<h2>… By Multiple Keys?</h2>
<p><strong>Problem</strong>: Given a list of dictionaries. How do you sort by multiple key value pairs?</p>
<p><strong>Minimal Example</strong>: Consider the following example where you want to sort a list of database entries (e.g. each stored as a dictionary) by value of the key <code>'username'</code>. If the <code>'username'</code> is the same, you use the <code>'joined'</code> value as a tiebreaker. If the <code>'joined'</code> date is the same, you use the <code>'age'</code> as a tie breaker.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">db = [{'username': 'Alice', 'joined': 2020, 'age': 23}, {'username': 'Bob', 'joined': 2018, 'age': 19}, {'username': 'Alice', 'joined': 2020, 'age': 31}] sorted_salaries = # ... Sorting Magic Here ... print(sorted_salaries)</pre>
<p>The output should look like this where the salary of Alice determines the order of the dictionaries:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'username': 'Alice', 'joined': 2020, 'age': 23}, {'username': 'Alice', 'joined': 2020, 'age': 31}, {'username': 'Bob', 'joined': 2018, 'age': 19}]</pre>
<p><strong>Solution</strong>: You’re going to define a key function with the <code>lambda</code> keyword. But instead of returning a single value to a given key, you return a tuple—one entry per value that should be considered. For example, the database entry <code>{'username': 'Alice', 'joined': 2020, 'age': 23}</code> is mapped to <code>('Alice', 2020, 23)</code>. This ensures that two tuples that have the same first tuple value will still be sorted correctly by using the second tuple value as a tiebreaker.</p>
<p>Here’s the code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Create the dictionary of user entries in your database
db = [{'username': 'Alice', 'joined': 2020, 'age': 23}, {'username': 'Bob', 'joined': 2018, 'age': 19}, {'username': 'Alice', 'joined': 2020, 'age': 31}] # Use the sorted() function with key argument to create a new list.
# Each dictionary list element is "reduced" to the tuple of values.
db_sorted = sorted(db, key=lambda row: (row['username'], row['joined'], row['age'])) # Print everything to the shell
print(db_sorted)
</pre>
<p>The output is the sorted dictionary. Note that the first dictionary has the smallest salary of Alice and the third dictionary has the largest salary of Alice.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'username': 'Alice', 'joined': 2020, 'age': 23}, {'username': 'Alice', 'joined': 2020, 'age': 31}, {'username': 'Bob', 'joined': 2018, 'age': 19}]</pre>
<p>In this example, the dictionary value for the key ‘joined’ was an integer number. But what if it’s a date?</p>
<h2>… By Date?</h2>
<p><strong>Problem</strong>: Given a list of dictionaries. How do you sort the list of dictionaries by <a href="https://blog.finxter.com/how-to-work-with-dates-and-times-in-python/" target="_blank" rel="noreferrer noopener">date</a>?</p>
<p><strong>Minimal Example</strong>: Consider the following example where you want to sort a list of database entries (e.g. each stored as a dictionary) by value of the key <code>'joined'</code> that is from type date or timedate. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">db = [{'username': 'Alice', 'joined': '2019-03-02', 'age': 23}, {'username': 'Bob', 'joined': '2020-08-08', 'age': 19}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}] db_sorted = # ... sorting magic here ... print(db_sorted)
</pre>
<p>The output should look like this where the salary of Alice determines the order of the dictionaries:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'username': 'Alice', 'joined': '2019-03-02', 'age': 23}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}, {'username': 'Bob', 'joined': '2020-08-08', 'age': 19}]</pre>
<p><strong>Solution</strong>: Define a key function with the <code>lambda</code> keyword. Simply return the string value for the key <code>'joined'</code> for a given dictionary. This return value is then used to sort the dictionaries in the list. </p>
<p>As the join dates are given as strings in the form year-month-day (e.g. <code>'2020-08-08'</code>), the default alphabetical sort will also lead to a sorted overall list of dictionaries: the dictionary row with the earliest join date will be the first in the resulting list.</p>
<p>Here’s the code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Create the dictionary of user entries in your database
db = [{'username': 'Alice', 'joined': '2019-03-02', 'age': 23}, {'username': 'Bob', 'joined': '2020-08-08', 'age': 19}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}] # Use the sorted() function with key argument to create a new list.
# Each dictionary list element is "reduced" to the join date.
db_sorted = sorted(db, key=lambda row: row['joined']) # Print everything to the shell
print(db_sorted)
</pre>
<p>The output is the sorted dictionary. Note that the first dictionary has the earliest and the third dictionary has the latest join date. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'username': 'Alice', 'joined': '2019-03-02', 'age': 23}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}, {'username': 'Bob', 'joined': '2020-08-08', 'age': 19}]</pre>
<p>You can use a similar method if the dictionary values are of format datetime as they are also comparable with default comparison operators <code>></code>, <code>&lt;</code>, <code>>=</code>, <code>&lt;=</code>, and <code>==</code>. [<a href="https://stackoverflow.com/questions/8142364/how-to-compare-two-dates" target="_blank" rel="noreferrer noopener">2</a>]</p>
<h2>… In Descending Order?</h2>
<p><strong>Problem</strong>: The default ordering of any Python list sort routine (<code>sorted()</code> and <code>list.sort()</code>) is in ascending order. This also holds if you sort a list of dictionaries. How can you sort in descending order?</p>
<p><strong>Solution</strong>: If you want to sort in descending order, you can do one of the following:</p>
<ul>
<li>Use slicing to reverse the sorted list.</li>
<li>Use the reverse=True argument of the <code>sorted()</code> or <code>list.sort()</code> methods. </li>
</ul>
<p>Both ways are equivalent. Have a look at the previous example first using the reverse argument:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Create the dictionary of user entries in your database
db = [{'username': 'Alice', 'joined': '2019-03-02', 'age': 23}, {'username': 'Bob', 'joined': '2020-08-08', 'age': 19}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}] # Use the sorted() function with key argument to create a new list.
# Each dictionary list element is "reduced" to the join date.
db_sorted = sorted(db, key=lambda row: row['joined'], reverse=True) # Print everything to the shell
print(db_sorted)</pre>
<p>Output:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'username': 'Bob', 'joined': '2020-08-08', 'age': 19}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}, {'username': 'Alice', 'joined': '2019-03-02', 'age': 23}]</pre>
<p>And second using slicing with negative step size (without the reverse argument):</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Create the dictionary of user entries in your database
db = [{'username': 'Alice', 'joined': '2019-03-02', 'age': 23}, {'username': 'Bob', 'joined': '2020-08-08', 'age': 19}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}] # Use the sorted() function with key argument to create a new list.
# Each dictionary list element is "reduced" to the join date.
db_sorted = sorted(db, key=lambda row: row['joined'])[::-1] # Print everything to the shell
print(db_sorted)</pre>
<p>Same output:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'username': 'Bob', 'joined': '2020-08-08', 'age': 19}, {'username': 'Alice', 'joined': '2019-03-04', 'age': 31}, {'username': 'Alice', 'joined': '2019-03-02', 'age': 23}]</pre>
<h2>… in Ascending Order?</h2>
<p>The default ordering of any Python list sort routine (<code>sorted()</code> and <code>list.sort()</code>) is in ascending order. This also holds if you sort a list of dictionaries. </p>
<h2>Where to Go From Here</h2>
<p>In this article, you’ve learned how to sort a list of dictionaries. In summary, use the <code>sorted()</code> method with a key function as argument. This gives you the flexibility to customize how exactly you want to sort the dictionary—just map each dictionary to a comparable value.</p>
<p>I’ve realized that professional coders tend to use dictionaries more often than beginners due to their superior understanding of the benefits of dictionaries. If you want to learn about those, check out my <a rel="noreferrer noopener" href="https://blog.finxter.com/python-dictionary/" target="_blank">in-depth tutorial of Python dictionaries</a>. </p>
<p>If you want to stop learning and start earning with Python, check out my free webinar <a href="https://blog.finxter.com/webinar-freelancer/">“How to Become a Python Freelance Developer?”</a>. It’s a great way of starting your thriving coding business online. </p>
<p><a href="https://blog.finxter.com/webinar-freelancer/" target="_blank" rel="noreferrer noopener">“[Webinar] How to Become a Python Freelance Developer?”</a></p>
</div>


https://www.sickgaming.net/blog/2020/04/02/python-how-to-sort-a-list-of-dictionaries/