【问题标题】:python sort list of objects by attribute based on predefined mapping [duplicate]python根据预定义映射按属性对对象列表进行排序[重复]
【发布时间】:2014-06-05 09:28:18
【问题描述】:

如何根据定义的映射按属性对 python 对象列表进行排序

例如

import random


class Obj(object):
    attr = None

    def __init__(self, attr):
        self.attr = attr

    def __repr__(self):
        return self.attr

attrs = ['GROUPA', 'GROUPB', 'GROUPC']

objects = []

for x in range(0, 10):
    objects.append(Obj(random.choice(attrs)))

objects = sorted(objects, key=lambda o: o.attr)

print '['
for o in objects:
    print o
print ']'

给我

[
    GROUPA
    GROUPA
    GROUPA
    GROUPA
    GROUPB
    GROUPB
    GROUPB
    GROUPB
    GROUPC
    GROUPC
]

这很好,但我想定义一个映射并在排序时考虑它,例如:

mapping = ['GROUPB', 'GROUPA', 'GROUPC']

结果:

[
    GROUPB
    GROUPB
    GROUPB
    GROUPB
    GROUPA
    GROUPA
    GROUPA
    GROUPA
    GROUPC
    GROUPC
]

然后得到这样的结果

【问题讨论】:

  • 运行您的示例不会在您编写时输出[ AAABBBCCC ],而是[ GROUPA GROUPA GROUPA GROUPA GROUPA GROUPB GROUPB GROUPB GROUPC GROUPC ]。也许您应该更正示例或示例输出?
  • 你试过什么?为什么不在课堂上实现comparison operators

标签: python


【解决方案1】:

您可以在字典中定义映射,键为要映射的字符,值为整数,值较低的字符具有较小的整数,如下所示:

mapping = {'B': 1, 'A': 2, 'C': 3}

然后你可以在你的 lambda 方法中使用这个字典:

sorted(objects, key=lambda o: mapping[o.attr])

【讨论】:

    【解决方案2】:

    您可以使用 sorted 内置函数的 cmp 参数。定义一个比较函数,您可以在其中检查元素在mapping 列表中的对应位置。比如:

    def compare(a, b):
        return cmp(mapping.index(a), mapping.index(b))
    

    然后,你可以像这样使用它:

    objects = sorted(objects, cmp=compare)
    

    更好的是,正如 cmets 中的一些建议,您可以绕过 cmp 参数并直接使用 key

    objects = sorted(objects, key=lambda o: mapping.index(o.attr))
    

    这样,您的代码将与 Python 3 兼容,并且更容易理解。

    【讨论】:

    • key 更易于使用且更高效(它被调用 n 次,而 cmp 被调用 O(n lg n) 次):sorted(objects, key=lambda o: mapping.index(o.attr))
    • cmp 已弃用,在 Python 3 中不可用,并且 OP 已经在使用更新的 key 参数,这是一个更好的选择。
    • 对,我自己太复杂了:)
    猜你喜欢
    • 2021-06-27
    • 2010-10-26
    • 2023-03-15
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    相关资源
    最近更新 更多