Сортировать список словарей по значениям, при этом некоторые элементы отсутствуют - PullRequest
2 голосов
/ 30 апреля 2019

У меня есть список таких списков:

a = [
   {'p': 3, 'id': 'ab1'},
   {'p': 10, 'id': 'ab2'},
   {'p': 5, 'id': 'ab3'},
   {'p': 8, 'id': 'ab4'},
   {'id': 'ab5'}
]

Я хочу отсортировать a по значению p.Если dict не имеет p, оставьте его позади.Я пробовал так:

print sorted(a, key=lambda i: i.get('p'))

и получил результат:

[{'id': 'ab5'}, {'p': 3, 'id': 'ab1'}, {'p': 5, 'id': 'ab3'}, {'p': 8, 'id': 'ab4'}, {'p': 10, 'id': 'ab2'}]

, но хочу получить:

[{'p': 3, 'id': 'ab1'}, {'p': 5, 'id': 'ab3'}, {'p': 8, 'id': 'ab4'}, {'p': 10, 'id': 'ab2'},{'id': 'ab5'}]

Что я могу сделать, чтобы получить правильныйрезультат проще?

Ответы [ 3 ]

4 голосов
/ 30 апреля 2019

Для обоих python2 и python3 вы можете сделать следующее, где я предполагаю, что если значение p отсутствует, я предполагаю значение sys.maxsize, которое гарантирует, что если мы пропустим значения для p,они всегда находятся в конце списка

import sys
a = [
   {'p': 3, 'id': 'ab1'},
   {'p': 10, 'id': 'ab2'},
   {'p': 5, 'id': 'ab3'},
   {'p': 8, 'id': 'ab4'},
   {'id': 'ab5'}
]

print(sorted(a, key=lambda i: i.get('p', sys.maxsize)))

, что даст вам

[{'p': 3, 'id': 'ab1'}, {'p': 5, 'id': 'ab3'}, {'p': 8, 'id': 'ab4'}, {'p': 10, 'id': 'ab2'}, {'id': 'ab5'}]

Другое решение, если сравнивать с sys.maxsize - это излишнее, - это выделить словари безkey p, сортируйте оставшийся словарь, содержащий ключ p, а затем расширяйте его, прикрепляя словари не p, как показано ниже.Это также позволяет нам не предоставлять значение по умолчанию для p в item.get()

import sys
a = [
   {'p': 3, 'id': 'ab1'},
   {'p': 10, 'id': 'ab2'},
   {'p': 5, 'id': 'ab3'},
   {'p': 8, 'id': 'ab4'},
   {'id': 'ab5'}
]

#Dictionaries with key p
p_items = [item for item in a if 'p' in item.keys()]

#Dictionaries not with key p
non_p_items = [item for item in a if 'p' not in item.keys()]

#Sort the p-key dictionaries
result = sorted(p_items, key=lambda i: i.get('p'))

#Attach non p-key dictionay items at end
result.extend(non_p_items)

print(result)
2 голосов
/ 30 апреля 2019

Вот вариант, который я предпочитаю, который не использует lambda:

import sys
from operator import methodcaller

a = [
   {'p': 3, 'id': 'ab1'},
   {'p': 10, 'id': 'ab2'},
   {'p': 5, 'id': 'ab3'},
   {'p': 8, 'id': 'ab4'},
   {'id': 'ab5'}
]

print(sorted(a, key=methodcaller('get', 'p', sys.maxsize)))
2 голосов
/ 30 апреля 2019

Используйте

a = [
   {'p': 3, 'id': 'ab1'},
   {'p': 10, 'id': 'ab2'},
   {'p': 5, 'id': 'ab3'},
   {'p': 8, 'id': 'ab4'},
   {'id': 'ab5'}
]

print(sorted(a, key=lambda i: i.get('p', "NA"))) #Setting a string as a default value. 
#python 3  --> https://stackoverflow.com/questions/49829732/sorting-a-mixed-list-of-ints-and-strings
print(sorted(a, key=lambda v: (isinstance(v.get('p', "NA"), str), v.get('p', "NA"))))

Выход:

[{'p': 3, 'id': 'ab1'}, {'p': 5, 'id': 'ab3'}, {'p': 8, 'id': 'ab4'}, {'p': 10, 'id': 'ab2'}, {'id': 'ab5'}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...