根据另一个列表的值的顺序对字典列表进行排序

12
我正在使用Python 2.7.3,尝试根据另一个列表中的值的顺序对字典列表进行排序。
例如:
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'}]

按照listOne中值的顺序排序listTwo,我们将得到以下结果:

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"])

有没有一种lambda表达式可以用来实现这个目的?必须有一种更紧凑、更简单的方法来按照我想要的顺序得到它。

2个回答

15

最简单的方法是使用 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
我在listOne中没有listTwo中的所有项目。因此,我会收到一个错误,指出“ValueError:4L不在列表中”。我该如何通过忽略这些项目来解决问题?或者也许对于那些项目应该以默认方式应用顺序。 - Hussain
默认值很容易设置。只需在第二个版本中使用 order_dict.get(x["eyecolor"], default) 即可。最合理的默认值可能是 -1(将未知值排序到开头)和 float('inf')(将它们排序到末尾)。删除值只需要稍微复杂一些。您需要在排序之前使用 filter(或等效的列表推导式)来过滤值。 - Blckknght

0
listOne = ['hazel', 'blue', 'green', 'brown', 'brown1']
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'},
    {'name': 'Amy', 'eyecolor': 'green2', 'height': '5 ft, 6 inches'},
    ]

print sorted(listTwo, key=lambda i: listOne.index(i['eyecolor']))

工作中

  1. 首先我们将遍历listTwo并获取眼睛颜色值。
  2. 使用该眼睛颜色值,我们需要检查在listOne上的该值的索引。
  3. 根据该索引,我们将排序值。

但是,在获取索引时,存在ValueError的可能性,因此我们需要处理它。

print sorted(listTwo, key=lambda i: (listOne.index(i['eyecolor'
             ]) if i['eyecolor'] in listOne else len(listOne) + 1))

为什么要在创建后转换列表?你可以将其创建为字典。sequence_dict = {'hazel': 0, 'blue': 1, 'green': 2, 'brown': 3} - Nomi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接