как отсортировать список словарей по значению словаря?

<p>у меня есть список словарей и хочу, чтобы каждый элемент сортировался по определенным значениям свойств.</p><p>примите во внимание массив ниже,</p><pre><code>[{'name':'homer', 'age':39}, {'name':'bart', 'age':10}] </code></pre><p>когда отсортировано по <code>name</code>, должно стать</p><pre><code>[{'name':'bart', 'age':10}, {'name':'homer', 'age':39}] </code></pre>

<p>это может выглядеть чище, используя ключ вместо cmp:</p><pre class="lang-py prettyprint-override"><code>newlist = sorted(list\_to\_be\_sorted, key=lambda k: k['name']) </code></pre><p>или, как предположили дж. ф. себастьян и другие,</p><pre class="lang-py prettyprint-override"><code>from operator import itemgetter newlist = sorted(list\_to\_be\_sorted, key=itemgetter('name')) </code></pre><p>для полноты (как указано в комментариях fitzgeraldsteele), добавьте <code>reverse=true</code> для сортировки по убыванию</p><pre class="lang-py prettyprint-override"><code>newlist = sorted(l, key=itemgetter('name'), reverse=true) </code></pre>

<pre><code>import operator </code></pre><p>чтобы отсортировать список словарей по ключу = 'name':</p><pre><code>list\_of\_dicts.sort(key=operator.itemgetter('name')) </code></pre><p>чтобы отсортировать список словарей по ключу = 'age':</p><pre><code>list\_of\_dicts.sort(key=operator.itemgetter('age')) </code></pre>

<p>если вы хотите отсортировать список по нескольким ключам, вы можете сделать следующее:</p><pre><code>my\_list = [{'name':'homer', 'age':39}, {'name':'milhouse', 'age':10}, {'name':'bart', 'age':10} ] sortedlist = sorted(my\_list , key=lambda elem: "%02d %s" % (elem['age'], elem['name'])) </code></pre><p>он довольно хакерский, так как он основан на преобразовании значений в одно строковое представление для сравнения, но работает для чисел, в том числе и отрицательных, как и ожидалось (хотя вам нужно будет соответствующим образом отформатировать строку с нулевыми дополнениями, если вы используете числа)</p>

<pre><code>my\_list = [{'name':'homer', 'age':39}, {'name':'bart', 'age':10}] my\_list.sort(lambda x,y : cmp(x['name'], y['name'])) </code></pre><p><code>my\_list</code> теперь будет тем, что вы хотите.</p><p><strong> (3 года спустя) отредактировано, чтобы добавить: </strong></p><p>новый аргумент <code>key</code> более эффективен и аккуратен. лучший ответ теперь выглядит так:</p><pre><code>my\_list = sorted(my\_list, key=lambda k: k['name']) </code></pre><p>... лямбда, imo, легче понять, чем <code>operator.itemgetter</code>, но ymmv.</p>

<pre><code>import operator a\_list\_of\_dicts.sort(key=operator.itemgetter('name')) </code></pre><p>«ключ» используется для сортировки по произвольному значению, а «itemgetter» устанавливает это значение в атрибут «name» каждого элемента.</p>

<p>я полагаю, вы имели в виду:</p><pre><code>[{'name':'homer', 'age':39}, {'name':'bart', 'age':10}] </code></pre><p>это будет отсортировано так:</p><pre><code>sorted(l,cmp=lambda x,y: cmp(x['name'],y['name'])) </code></pre>

<p>используя преобразование шварца из perl,</p><pre><code>py = [{'name':'homer', 'age':39}, {'name':'bart', 'age':10}] </code></pre><p>делать</p><pre><code>sort\_on = "name" decorated = [(dict\_[sort\_on], dict\_) for dict\_ in py] decorated.sort() result = [dict\_ for (key, dict\_) in decorated] </code></pre><p>дает</p><pre><code>>>> result [{'age': 10, 'name': 'bart'}, {'age': 39, 'name': 'homer'}] </code></pre><p>подробнее о <a href="http://en.wikipedia.org/wiki/schwartzian\_transform">перл шварцян преобразование</a> </p><blockquote> <p>в информатике преобразование шварца является программированием на perl идиома используется для повышения эффективности сортировки списка предметов. это идиома подходит для сортировки на основе сравнения, когда упорядочение фактически основано на упорядочении определенного свойства (ключа) элементы, где вычисление этого свойства является интенсивной операцией, которая должно быть выполнено минимальное количество раз. шварцян transform отличается тем, что не использует именованные временные массивы.</p> </blockquote>

<pre><code>a = [{'name':'homer', 'age':39}, ...] # this changes the list a a.sort(key=lambda k : k['name']) # this returns a new list (a is not modified) sorted(a, key=lambda k : k['name']) </code></pre>

<p>вы можете использовать пользовательскую функцию сравнения или передать функцию, которая вычисляет пользовательский ключ сортировки. это обычно более эффективно, поскольку ключ рассчитывается только один раз для каждого элемента, тогда как функция сравнения будет вызываться много раз.</p><p>вы могли бы сделать это так:</p><pre><code>def mykey(adict): return adict['name'] x = [{'name': 'homer', 'age': 39}, {'name': 'bart', 'age':10}] sorted(x, key=mykey) </code></pre><p>но стандартная библиотека содержит стандартную процедуру для получения элементов произвольных объектов: <code>itemgetter</code>. так что попробуйте это вместо:</p><pre><code>from operator import itemgetter x = [{'name': 'homer', 'age': 39}, {'name': 'bart', 'age':10}] sorted(x, key=itemgetter('name')) </code></pre>

<p>вы должны реализовать собственную функцию сравнения, которая будет сравнивать словари по значениям именных ключей. смотрите <a href="http://wiki.python.org/moin/howto/sorting">сортировка мини-как то из pythoninfo wiki</a> </p>

<p>я попробовал что-то вроде этого:</p><pre><code>my\_list.sort(key=lambda x: x['name']) </code></pre><p>это сработало и для целых чисел.</p>

<p>иногда нам нужно использовать <code>lower()</code> например</p><pre><code>lists = [{'name':'homer', 'age':39}, {'name':'bart', 'age':10}, {'name':'abby', 'age':9}] lists = sorted(lists, key=lambda k: k['name']) print(lists) # [{'name':'bart', 'age':10}, {'name':'homer', 'age':39}, {'name':'abby', 'age':9}] lists = sorted(lists, key=lambda k: k['name'].lower()) print(lists) # [ {'name':'abby', 'age':9}, {'name':'bart', 'age':10}, {'name':'homer', 'age':39}] </code></pre>

<p>вот альтернативное общее решение - оно сортирует элементы dict по ключам и значениям .. преимущество этого - не нужно указывать ключи, и оно все равно будет работать, если некоторые ключи отсутствуют в некоторых словарях.</p><pre><code>def sort\_key\_func(item): """ helper function used to sort list of dicts :param item: dict :return: sorted list of tuples (k, v) """ pairs = [] for k, v in item.items(): pairs.append((k, v)) return sorted(pairs) sorted(a, key=sort\_key\_func) </code></pre>

<p>использование пакета pandas - это еще один метод, хотя в широком масштабе его время выполнения намного медленнее, чем у традиционных методов, предложенных другими:</p><pre><code>import pandas as pd listofdicts = [{'name':'homer', 'age':39}, {'name':'bart', 'age':10}] df = pd.dataframe(listofdicts) df = df.sort\_values('name') sorted\_listofdicts = df.t.to\_dict().values() </code></pre><p>вот некоторые эталонные значения для крошечного списка и большого (более 100 тыс.) списка диктов:</p><pre><code>setup\_large = "listofdicts = [];\ [listofdicts.extend(({'name':'homer', 'age':39}, {'name':'bart', 'age':10})) for \_ in range(50000)];\ from operator import itemgetter;import pandas as pd;\ df = pd.dataframe(listofdicts);" setup\_small = "listofdicts = [];\ listofdicts.extend(({'name':'homer', 'age':39}, {'name':'bart', 'age':10}));\ from operator import itemgetter;import pandas as pd;\ df = pd.dataframe(listofdicts);" method1 = "newlist = sorted(listofdicts, key=lambda k: k['name'])" method2 = "newlist = sorted(listofdicts, key=itemgetter('name')) " method3 = "df = df.sort\_values('name');\ sorted\_listofdicts = df.t.to\_dict().values()" import timeit t = timeit.timer(method1, setup\_small) print('small method lc: ' + str(t.timeit(100))) t = timeit.timer(method2, setup\_small) print('small method lc2: ' + str(t.timeit(100))) t = timeit.timer(method3, setup\_small) print('small method pandas: ' + str(t.timeit(100))) t = timeit.timer(method1, setup\_large) print('large method lc: ' + str(t.timeit(100))) t = timeit.timer(method2, setup\_large) print('large method lc2: ' + str(t.timeit(100))) t = timeit.timer(method3, setup\_large) print('large method pandas: ' + str(t.timeit(1))) #small method lc: 0.000163078308105 #small method lc2: 0.000134944915771 #small method pandas: 0.0712950229645 #large method lc: 0.0321750640869 #large method lc2: 0.0206089019775 #large method pandas: 5.81405615807 </code></pre>

<p>скажем, у меня есть словарь d с элементами ниже. для сортировки просто используйте ключевой аргумент в sorted для передачи пользовательской функции, как показано ниже</p><pre><code>d = {'eggs': 3, 'ham': 1, 'spam': 2} def get\_count(tuple): return tuple[1] sorted(d.items(), key = get\_count, reverse=true) or sorted(d.items(), key = lambda x: x[1], reverse=true) avoiding get\_count function call </code></pre><p> <a href="https://wiki.python.org/moin/howto/sorting/#key\_functions">https://wiki.python.org/moin/howto/sorting/#key\_functions</a> </p>

<p>вот <a href="https://stackoverflow.com/questions/1143671/python-sorting-list-of-dictionaries-by-multiple-keys/1144405">мой ответ на связанный вопрос о сортировке по нескольким столбцам</a> . это также работает для вырожденного случая, когда число столбцов только один.</p>

<p>если вам не нужен исходный <code>list</code> из <code>dictionaries</code>, вы можете изменить его на месте с помощью метода <code>sort()</code>, используя функцию пользовательской клавиши.</p><p>ключевая функция:</p><pre><code>def get\_name(d): """ return the value of a key in a dictionary. """ return d["name"] </code></pre><p><code>list</code> для сортировки:</p><pre><code>data\_one = [{'name': 'homer', 'age': 39}, {'name': 'bart', 'age': 10}] </code></pre><p>сортировка по месту:</p><pre><code>data\_one.sort(key=get\_name) </code></pre><p>если вам нужен оригинальный <code>list</code>, вызовите функцию <code>sorted()</code>, передав ей <code>list</code> и функцию ключа, затем присвойте возвращенный отсортированный <code>list</code> новой переменной:</p><pre><code>data\_two = [{'name': 'homer', 'age': 39}, {'name': 'bart', 'age': 10}] new\_data = sorted(data\_two, key=get\_name) </code></pre><p>печать <code>data\_one</code> и <code>new\_data</code>.</p><pre><code>>>> print(data\_one) [{'name': 'bart', 'age': 10}, {'name': 'homer', 'age': 39}] >>> print(new\_data) [{'name': 'bart', 'age': 10}, {'name': 'homer', 'age': 39}] </code></pre>

<p>вы можете использовать<strong> itemgetter </strong>, если вы хотите рассмотреть производительность.<strong> itemgetter </strong>обычно работает немного быстрее, чем<strong> lambda </strong>.</p><pre><code>from operator import itemgetter result = sorted(data, key=itemgetter('age')) # this will sort list by property order 'age'. </code></pre>

<p>вы можете использовать следующий код</p><pre><code>sorted\_dct = sorted(dct\_name.items(), key = lambda x : x[1]) </code></pre>