【问题标题】:Complex sort dictionary into sorted list复杂的排序字典到排序列表
【发布时间】:2014-02-25 05:20:20
【问题描述】:

我有以下课程:

class SalesRecord:
    name = ''
    dollarsSpent = 0
    itemsPurchased = 0
    itemsSold = 0
    position = 0

我还有一个字典,它由一堆以 SalesRecord.name 为键的 SalesRecords 构成。如何使用以下标准将值排序到排序列表中(假设所有内容都是整数):

  1. 按使用的美元数降序排序
  2. 然后按 itemsPurchased - itemsSold desc
  3. 然后按物品购买描述
  4. 然后按位置 asc

另外,只是好奇,但是这种排序的整体运行时间是多少?最坏情况下需要迭代4次吗?

【问题讨论】:

  • 你能展示一下你的字典的结构吗?
  • 只是一个简单的字典结构。例如:sales['Johnson1'] = the SalesRecord object where SalesRecord.name = 'Johnson1'

标签: python list sorting dictionary


【解决方案1】:

使用复合键。

sorted((k, v) for (k, v) in somedict, key=lambda (k, v):
  (-v.dollarsSpent, -(v.itemsPurchased - v.itemsSold),
  -v.itemsPurchased, v.position))

【讨论】:

  • 与 user2357112 提出的选项 1 相比,这样做有什么好处?
  • 它不会向范围添加另一个名称。不管怎样,这没什么大不了的。
【解决方案2】:

你有两个选择。这两个选项都以线性时间运行,O(nlog(n)),但您可以考虑一个更具可读性。您可以使用复合排序键:

def sortkey(salesrecord):
    r = salesrecord
    return (
        -r.dollarsSpent,
        -r.itemsPurchased + r.itemsSold,
        -r.itemsPurchased,
        r.position
    )
sorted(salesdict.values(), key=sortkey)

或者多次排序,依赖排序算法的稳定性:

l = salesdict.values()
l.sort(key=lambda r: r.position)
l.sort(key=lambda r: r.itemsPurchased, reverse=True)
l.sort(key=lambda r: r.itemsPurchased - r.itemsSold, reverse=True)
l.sort(key=lambda r: r.dollarsSpent, reverse=True)

使用stable sort,您可以通过按每个键从最低优先级到最高排序来按具有不同优先级的多个键进行排序。在按优先级较高的键排序后,通过该键比较相等的项目保证保持在低优先级键排序后的顺序。

【讨论】:

  • 这两个选项是否仍会以 O(nlog(n)) 的 timsorts 最坏情况时间排序?
  • @Gyrien:是的。一个可能有一个更差的常数因子,但它可能无关紧要。
  • 谢谢!另外,为什么在第二种情况下你先按 r.position 排序?
  • @Gyrien:在itemsPurchased排序后,任何购买商品数量相同的记录将按照position排序后的顺序排列,因此列表将按以下顺序排序购买的物品,然后定位。这个原则也适用于接下来的两种。
【解决方案3】:

最简单的方法是利用sort stability 在多个阶段进行排序(首先按位置,然后按购买的物品降序等)。

这比看起来要便宜,因为TimSort algorithm 利用了已经部分排序的元素。

这种方法也比尝试构建一个过于复杂的key-function 更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多