2016-02-28 4 views
5

У меня есть объект, который является списком списков словарей:Сортировка списка списков словарей в Python

myObject =[[{ "play": 5.00, "id": 1, "uid": "abc" }, \ 
      { "play": 1.00, "id": 2, "uid": "def" }], \ 
      [{ "play": 6.00, "id": 3, "uid": "ghi" }, \ 
      { "play": 7.00, "id": 4, "uid": "jkl" }], \ 
      [{ "play": 3.00, "id": 5, "uid": "mno" }, \ 
      { "play": 1.00, "id": 6, "uid": "pqr" }]] 

Я хочу, чтобы отсортировать список по сумме play значений в словарях каждой вложенной список. Объект затем будет отсортирован, как это:

myObject =[[{ "play": 6.00, "id": 3, "uid": "ghi" }, \ 
      { "play": 7.00, "id": 4, "uid": "jkl" }], \ 
      [{ "play": 5.00, "id": 1, "uid": "abc" }, \ 
      { "play": 1.00, "id": 2, "uid": "def" }], \ 
      [{ "play": 3.00, "id": 5, "uid": "mno" }, \ 
      { "play": 1.00, "id": 6, "uid": "pqr" }]] 

Если бы это было просто список dicts затем:

sorted(myObject, key=sum(map(itemgetter(play))), reverse=True)

будет работать. Я не могу понять, как это сделать, не перебирая список, вычисляя сумму, а затем сортируя. Это то, что я делаю сейчас, но я пытаюсь повысить эффективность этого кода, удалив циклы, потому что в моем списке насчитывается 100 миллионов миллионов списков.

+2

Как примечание: в этом случае вам не нужны завершающие '' '' '' продолжения строки. Поскольку строки заканчиваются запятой, а литералы в списке все еще «открыты», Python автоматически ожидает, что следующая строка продолжит работу там. – poke

ответ

4

Ваша идея уже очень хорошо, чтобы использовать пользовательскую функцию клавиши при сортировке и использовании sum, map и itemgetter на ключ play:

key=sum(map(itemgetter(play))) 

У вас есть проблемы есть хотя: key аргумент ожидает функцию, которая берет элемент вашего списка, который вы сортируете. Но ни sum, ни map не возвращают функцию, поэтому вы не можете использовать ее в качестве ключевой функции. Вместо этого вы можете создать функцию лямбда, которая выполняет эту комбинацию для каждого элемента.

Другие проблемы заключаются в том, что play должен быть строкой 'play' и что map должен принять подсловитель в качестве аргумента. Таким образом, ваша ключевая функция будет выглядеть так:

key=lambda x: sum(map(itemgetter('play'), x)) 

Это кстати. функционально эквивалентно следующему генератора понимания, который может быть более удобным для чтения:

key=lambda x: sum(y['play'] for y in x) 

Используя это с sorted должны работать, но вы должны рассмотреть сортировку списка непосредственно с помощью list.sort вместо:.

>>> myObject = [[{ "play": 5.00, "id": 1, "uid": "abc" }, 
       { "play": 1.00, "id": 2, "uid": "def" }], 
       [{ "play": 6.00, "id": 3, "uid": "ghi" }, 
       { "play": 7.00, "id": 4, "uid": "jkl" }], 
       [{ "play": 3.00, "id": 5, "uid": "mno" }, 
       { "play": 1.00, "id": 6, "uid": "pqr" }]] 

>>> myObject.sort(key=lambda x: sum(y['play'] for y in x), reverse=True) 

>>> for x in myObject: 
     print(x) 

[{'play': 6.0, 'uid': 'ghi', 'id': 3}, {'play': 7.0, 'uid': 'jkl', 'id': 4}] 
[{'play': 5.0, 'uid': 'abc', 'id': 1}, {'play': 1.0, 'uid': 'def', 'id': 2}] 
[{'play': 3.0, 'uid': 'mno', 'id': 5}, {'play': 1.0, 'uid': 'pqr', 'id': 6}] 

(КСТАТИ myObject является вид плохого имени для перечня вещей.)


Что касается эффективности или сложность вашей проблемы, вы действительно не можете избежать необходимости прокручивать каждый подсписчик в конце концов. Невозможно определить сумму этих значений, не глядя на значения, поэтому, очевидно, вы не сможете избежать этого.

Однако вы должны следить за тем, чтобы каждая сумма вычислялась только один раз, чтобы избежать необходимости просматривать элементы в подсписках более одного раза. К счастью, сортировка с использованием list.sort делает именно гарантировать, что по умолчанию:

ключ, соответствующий каждому элементу в списке вычисляется один раз, а затем используется для всего процесса сортировки.

Таким образом, у вас будет очень эффективное решение этой проблемы сортировки.

+0

Если это не будет 'reverse = True', чтобы получить максимальный результат –

+0

@PaulRooney О да, я пропустил эту деталь в вопросе (хотя это не имеет особого отношения к проблеме сортировки). Спасибо! – poke

Смежные вопросы