python 字典按列表排序
python dictionary sorted by list
我有一个列表
category = ['Toy','Cloth','Food','Auto']
我还有一本字典(其中第一个 A、B、C... 是项目名称,每个列表中的第一个元素是类别,第二个是价格。
inventory = {'A':['Food', 5], 'B':['Food', 6],
'C':['Auto', 5], 'D':['Cloth', 14],
'E':['Toy',19], 'F':['Cloth', 13], 'G':['Toy',20], 'H':['Toy',11]}
我希望首先按列表中类别的顺序对其进行排序,其次,我希望它们按价格排序(同时保持类别顺序),这样结果如下所示。 ..
inventory_sorted = {'G':['Toy',20],'E':['Toy',19], 'H':['Toy',11], 'D':['Cloth', 14],
'F':['Cloth', 13], 'B':['Food', 6],'A':['Food', 5],'C':['Auto', 5],}
能否请您提供两个步骤的过程,首先是按列表的类别排序,第二个是按保留类别排序的价格(反向)排序。如果您使用的是 Lambda,请给我一些叙述,以便我更好地理解。我是 Lamda 表达式的新手。非常感谢
您无法对 Python dict
对象进行排序,因为它们未排序。最多,您可以生成一个排序的(键值)对序列。如果您想要包含订单的映射,则可以将这些对提供给 collections.OrderedDict()
object。
将您的 category
订单转换为映射以获取订单,然后将其与价格一起用于排序键。由于您希望价格按 降序 顺序排序,因此您需要 return negative price:
cat_order = {cat: i for i, cat in enumerate(category)}
inventory_sorted = sorted(inventory.items(),
key=lambda i: (cat_order[i[1][0]], -i[1][1]))
每个键值对传递i
参数; i[1]
是价值,i[1][0]
是类别,i[1][1]
是价格。
这会按指定顺序生成键值对:
>>> category = ['Toy','Cloth','Food','Auto']
>>> inventory = {'A':['Food', 5], 'B':['Food', 6],
... 'C':['Auto', 5], 'D':['Cloth', 14],
... 'E':['Toy',19], 'F':['Cloth', 13], 'G':['Toy',20], 'H':['Toy',11]}
>>> cat_order = {cat: i for i, cat in enumerate(category)}
>>> sorted(inventory.items(), key=lambda i: (cat_order[i[1][0]], -i[1][1]))
[('G', ['Toy', 20]), ('E', ['Toy', 19]), ('H', ['Toy', 11]), ('D', ['Cloth', 14]), ('F', ['Cloth', 13]), ('B', ['Food', 6]), ('A', ['Food', 5]), ('C', ['Auto', 5])]
>>> from pprint import pprint
>>> pprint(_)
[('G', ['Toy', 20]),
('E', ['Toy', 19]),
('H', ['Toy', 11]),
('D', ['Cloth', 14]),
('F', ['Cloth', 13]),
('B', ['Food', 6]),
('A', ['Food', 5]),
('C', ['Auto', 5])]
一个OrderedDict()
对象直接接受这个序列:
>>> from collections import OrderedDict
>>> OrderedDict(sorted(inventory.items(), key=lambda i: (cat_order[i[1][0]], -i[1][1])))
OrderedDict([('G', ['Toy', 20]), ('E', ['Toy', 19]), ('H', ['Toy', 11]), ('D', ['Cloth', 14]), ('F', ['Cloth', 13]), ('B', ['Food', 6]), ('A', ['Food', 5]), ('C', ['Auto', 5])])
您可以通过以下方式获得此信息:
sorted(inventory.items(), key=lambda t: category.index(t[1][0]))
之所以有效,是因为:
inventory.items()
把你的字典变成一个元组列表,它可以保留一个顺序
key
函数根据 t[1][0]
在您的 category
列表中出现的位置进行排序,并且
t
类似于 ('G', ('Toy', 20))
所以 t[1]
是 ('Toy', 20)
而 t[1][0]
是 'Toy'
.
但是您不能从这里返回到标准 dict
(即使这很容易),因为您会再次失去排序,使排序变得毫无意义。因此,您要么必须使用这种格式的数据,要么使用已经提到的 collections.OrderedDict
之类的东西。
另一种完全不同的方法,相当强大,是
- 使用pythonclass制作数据结构,
- 将数据存储在列表中
- 使用 key=attrgetter('variable')
对列表进行排序
下面是一段示例代码:
class Item:
def __init__(self,label,category,number):
self.label = label
self.category = category
self.number = number
def __repr__(self):
return "Item(%s,%s,%d)"%(self.label,self.category,self.number)
def __str__(self):
return "%s: %s,%d"%(self.label,self.category,self.number)
inventory = []
inventory.append(Item("A","Food",5))
inventory.append(Item("B","Food",6))
inventory.append(Item("C","Auto",5))
inventory.append(Item("D","Cloth",14))
inventory.append(Item("E","Toy",19))
inventory.append(Item("F","Cloth",13))
inventory.append(Item("G","Toy",20))
inventory.append(Item("H","Toy",11))
inventory.sort(key=attrgetter('number'),reverse=True)
inventory.sort(key=attrgetter('category'))
这样做的好处是,排序的目的是保持上一个排序的顺序,所以调用它两次(就像我上面所做的那样)可以让你主要按类别排序,但按次要数。您可以根据需要对任意数量的排序键执行此操作。
您还可以在项目中添加您想要的任何其他信息。
categories = ['Toy','Cloth','Food','Auto']
inventory = {'A':['Food', 5], 'B':['Food', 6],
'C':['Auto', 5], 'D':['Cloth', 14],
'E':['Toy',19], 'F':['Cloth', 13], 'G':['Toy',20], 'H':['Toy',11]}
from collections import OrderedDict
inventory_sorted = OrderedDict()
for category in categories:
same_category = [(key, num) for key, (cat, num) in inventory.items() if cat == category]
for (key, num) in sorted(same_category, key=lambda (_, num): num, reverse=True):
inventory_sorted[key] = [category, num]
for key, value in inventory_sorted.items():
print key, value
由于 dictionaries
是无序的,我们将使用 OrderedDict
来实现您的目标。
工作原理:
same_category
是一个简单的列表推导式,如果项目与当前循环类别相同,它将过滤项目,它将形成一个由 (key, num) 对的元组组成的列表。
然后我们使用数字对这个新列表进行排序,执行此操作的行是 key=lambda (_, num): num
,这将解包元组,使用 _
丢弃密钥,然后按 num
排序],我们反转它,所以它首先显示高数字。
然后我们将每个 [category, num]
对添加到 key
.
中的 OrderedDict inventory_sorted
结果:
G ['Toy', 20]
E ['Toy', 19]
H ['Toy', 11]
D ['Cloth', 14]
F ['Cloth', 13]
B ['Food', 6]
A ['Food', 5]
C ['Auto', 5]
我有一个列表
category = ['Toy','Cloth','Food','Auto']
我还有一本字典(其中第一个 A、B、C... 是项目名称,每个列表中的第一个元素是类别,第二个是价格。
inventory = {'A':['Food', 5], 'B':['Food', 6],
'C':['Auto', 5], 'D':['Cloth', 14],
'E':['Toy',19], 'F':['Cloth', 13], 'G':['Toy',20], 'H':['Toy',11]}
我希望首先按列表中类别的顺序对其进行排序,其次,我希望它们按价格排序(同时保持类别顺序),这样结果如下所示。 ..
inventory_sorted = {'G':['Toy',20],'E':['Toy',19], 'H':['Toy',11], 'D':['Cloth', 14],
'F':['Cloth', 13], 'B':['Food', 6],'A':['Food', 5],'C':['Auto', 5],}
能否请您提供两个步骤的过程,首先是按列表的类别排序,第二个是按保留类别排序的价格(反向)排序。如果您使用的是 Lambda,请给我一些叙述,以便我更好地理解。我是 Lamda 表达式的新手。非常感谢
您无法对 Python dict
对象进行排序,因为它们未排序。最多,您可以生成一个排序的(键值)对序列。如果您想要包含订单的映射,则可以将这些对提供给 collections.OrderedDict()
object。
将您的 category
订单转换为映射以获取订单,然后将其与价格一起用于排序键。由于您希望价格按 降序 顺序排序,因此您需要 return negative price:
cat_order = {cat: i for i, cat in enumerate(category)}
inventory_sorted = sorted(inventory.items(),
key=lambda i: (cat_order[i[1][0]], -i[1][1]))
每个键值对传递i
参数; i[1]
是价值,i[1][0]
是类别,i[1][1]
是价格。
这会按指定顺序生成键值对:
>>> category = ['Toy','Cloth','Food','Auto']
>>> inventory = {'A':['Food', 5], 'B':['Food', 6],
... 'C':['Auto', 5], 'D':['Cloth', 14],
... 'E':['Toy',19], 'F':['Cloth', 13], 'G':['Toy',20], 'H':['Toy',11]}
>>> cat_order = {cat: i for i, cat in enumerate(category)}
>>> sorted(inventory.items(), key=lambda i: (cat_order[i[1][0]], -i[1][1]))
[('G', ['Toy', 20]), ('E', ['Toy', 19]), ('H', ['Toy', 11]), ('D', ['Cloth', 14]), ('F', ['Cloth', 13]), ('B', ['Food', 6]), ('A', ['Food', 5]), ('C', ['Auto', 5])]
>>> from pprint import pprint
>>> pprint(_)
[('G', ['Toy', 20]),
('E', ['Toy', 19]),
('H', ['Toy', 11]),
('D', ['Cloth', 14]),
('F', ['Cloth', 13]),
('B', ['Food', 6]),
('A', ['Food', 5]),
('C', ['Auto', 5])]
一个OrderedDict()
对象直接接受这个序列:
>>> from collections import OrderedDict
>>> OrderedDict(sorted(inventory.items(), key=lambda i: (cat_order[i[1][0]], -i[1][1])))
OrderedDict([('G', ['Toy', 20]), ('E', ['Toy', 19]), ('H', ['Toy', 11]), ('D', ['Cloth', 14]), ('F', ['Cloth', 13]), ('B', ['Food', 6]), ('A', ['Food', 5]), ('C', ['Auto', 5])])
您可以通过以下方式获得此信息:
sorted(inventory.items(), key=lambda t: category.index(t[1][0]))
之所以有效,是因为:
inventory.items()
把你的字典变成一个元组列表,它可以保留一个顺序key
函数根据t[1][0]
在您的category
列表中出现的位置进行排序,并且t
类似于('G', ('Toy', 20))
所以t[1]
是('Toy', 20)
而t[1][0]
是'Toy'
.
但是您不能从这里返回到标准 dict
(即使这很容易),因为您会再次失去排序,使排序变得毫无意义。因此,您要么必须使用这种格式的数据,要么使用已经提到的 collections.OrderedDict
之类的东西。
另一种完全不同的方法,相当强大,是
- 使用pythonclass制作数据结构,
- 将数据存储在列表中
- 使用 key=attrgetter('variable') 对列表进行排序
下面是一段示例代码:
class Item:
def __init__(self,label,category,number):
self.label = label
self.category = category
self.number = number
def __repr__(self):
return "Item(%s,%s,%d)"%(self.label,self.category,self.number)
def __str__(self):
return "%s: %s,%d"%(self.label,self.category,self.number)
inventory = []
inventory.append(Item("A","Food",5))
inventory.append(Item("B","Food",6))
inventory.append(Item("C","Auto",5))
inventory.append(Item("D","Cloth",14))
inventory.append(Item("E","Toy",19))
inventory.append(Item("F","Cloth",13))
inventory.append(Item("G","Toy",20))
inventory.append(Item("H","Toy",11))
inventory.sort(key=attrgetter('number'),reverse=True)
inventory.sort(key=attrgetter('category'))
这样做的好处是,排序的目的是保持上一个排序的顺序,所以调用它两次(就像我上面所做的那样)可以让你主要按类别排序,但按次要数。您可以根据需要对任意数量的排序键执行此操作。
您还可以在项目中添加您想要的任何其他信息。
categories = ['Toy','Cloth','Food','Auto']
inventory = {'A':['Food', 5], 'B':['Food', 6],
'C':['Auto', 5], 'D':['Cloth', 14],
'E':['Toy',19], 'F':['Cloth', 13], 'G':['Toy',20], 'H':['Toy',11]}
from collections import OrderedDict
inventory_sorted = OrderedDict()
for category in categories:
same_category = [(key, num) for key, (cat, num) in inventory.items() if cat == category]
for (key, num) in sorted(same_category, key=lambda (_, num): num, reverse=True):
inventory_sorted[key] = [category, num]
for key, value in inventory_sorted.items():
print key, value
由于 dictionaries
是无序的,我们将使用 OrderedDict
来实现您的目标。
工作原理:
same_category
是一个简单的列表推导式,如果项目与当前循环类别相同,它将过滤项目,它将形成一个由 (key, num) 对的元组组成的列表。
然后我们使用数字对这个新列表进行排序,执行此操作的行是 key=lambda (_, num): num
,这将解包元组,使用 _
丢弃密钥,然后按 num
排序],我们反转它,所以它首先显示高数字。
然后我们将每个 [category, num]
对添加到 key
.
inventory_sorted
结果:
G ['Toy', 20]
E ['Toy', 19]
H ['Toy', 11]
D ['Cloth', 14]
F ['Cloth', 13]
B ['Food', 6]
A ['Food', 5]
C ['Auto', 5]