繁体   English   中英

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()对象

category订单转换为映射以获取订单,然后将其与价格一起用于排序键。 由于您希望价格按降序排列,因此需要返回价格:

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功能的排序基于category列表中t[1][0]出现的位置,以及
  • t将类似于('G', ('Toy', 20))因此t[1]('Toy', 20)t[1][0]'Toy'

但是您不能从中返回标准dict (即使很简单),因为您将再次失去订单,使排序毫无意义。 因此,您将不得不使用这种格式的数据,或者使用如上所述的collections.OrderedDict东西。

执行此操作的另一种完全不同的方法(功能非常强大)是:

  1. 使用python类制作数据结构,
  2. 将数据存储在列表中
  3. 使用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是一个简单的列表same_category ,如果与当前循环类别属于同一类别,则过滤它们,它将形成一个列表,该列表由(键,数字)对的元组组成。

然后,我们使用数字对这个新列表进行排序,执行此操作的行是key=lambda (_, num): num ,这将拆开元组,使用_丢弃键,然后按num排序,将其反转,从而显示高数字优先。

然后我们添加的每个的那些[category, num]对向OrderedDict inventory_sortedkey

结果:

G ['Toy', 20]
E ['Toy', 19]
H ['Toy', 11]
D ['Cloth', 14]
F ['Cloth', 13]
B ['Food', 6]
A ['Food', 5]
C ['Auto', 5]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM