2013-03-27 5 views
7

Я использую python 2.7.3, и я пытаюсь отсортировать список словарей на основе порядка значений другого списка.Сортировка списка словарей на основе порядка значений другого списка

IE:

listOne = ['hazel', 'blue', 'green', 'brown'] 
listTwo = [{'name': 'Steve', 'eyecolor': 'hazel', 'height': '5 ft. 11 inches'}, 
      {'name': 'Mark', 'eyecolor': 'brown', 'height': '6 ft. 2 inches'}, 
      {'name': 'Mike', 'eyecolor': 'blue', 'height': '6 ft. 0 inches'}, 
      {'name': 'Ryan', 'eyecolor': 'brown', 'height': '6 ft, 0 inches'}, 
      {'name': 'Amy', 'eyecolor': 'green', 'height': '5 ft, 6 inches'}] 

Сортировка listTwo основаны от порядка значений в Listone, мы в конечном итоге следующее:

print listTwo 
[{'name': 'Steve', 'eyecolor': 'hazel', 'height': '5 ft. 11 inches'}, 
{'name': 'Mike', 'eyecolor': 'blue', 'height': '6 ft. 0 inches'}, 
{'name': 'Amy', 'eyecolor': 'green', 'height': '5 ft, 6 inches'}, 
{'name': 'Mark', 'eyecolor': 'brown', 'height': '6 ft. 2 inches'}, 
{'name': 'Ryan', 'eyecolor': 'brown', 'height': '6 ft, 0 inches'}] 

я в конце концов нужно вывести этот текст, так что Я сделал, чтобы отобразить его правильно (в правильном порядке):

for x in xrange(len(listOne)): 
    for y in xrange(len(listTwo)): 
     if listOne[x] == listTwo[y]["eyecolor"]: 
      print "Name: " + str(listTwo[y]["name"]), 
      print "Eye Color: " + str(listTwo[y]["eyecolor"]), 
      print "Height: " + str(listTwo[y]["height"]) 

Является ли что-то вроде лямбда-выражения, которое можно использовать, чтобы это произошло? Должен быть более компактный, менее сложный способ получить его в том порядке, в котором я хочу.

ответ

8

Самый простой способ будет использовать list.index для генерирования значения сортировки в списке словарей:

listTwo.sort(key=lambda x: listOne.index(x["eyecolor"])) 

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

order_dict = {color: index for index, color in enumerate(listOne)} 
listTwo.sort(key=lambda x: order_dict[x["eyecolor"]]) 

Если вы не хотите, чтобы изменить listTwo, вы можете использовать встроенный в sorted функции вместо метода list.sort. Он возвращает отсортированную копию списка, а не сортировку на месте.

+1

Этот индексный словарь был именно тем, что я искал. Я действительно хочу отсортировать список на месте, вместо того, чтобы возвращать новый отсортированный список, поэтому я буду использовать list.sort. Благодаря! – Fifteen

+0

У меня нет всех предметов из listTwo в listOne. Поэтому я получаю сообщение об ошибке «ValueError: 4L не в списке». Как мне решить, игнорируя эти элементы? Или, может быть, порядок должен применяться по умолчанию для тех – Hussain

+0

Значение по умолчанию будет довольно простым. Просто используйте 'order_dict.get (x [" eyecolor "], по умолчанию)' во второй версии. Наиболее разумными значениями по умолчанию являются, вероятно, '-1' (для сортировки неизвестных значений в начале) и' float ('inf') '(сортировать их в конце). Удаление значений было бы немного сложнее. Перед сортировкой вам нужно будет использовать 'filter' (или эквивалентное представление списка). – Blckknght

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