我有一个名为Shareholder的类,每个Shareholder可以具有4个职位之一:总裁,副总统,秘书或司库(按顺序)。

我想按其职称对股东列表进行排序,但是除了使这种可怕的cmp函数像这样,我不知道该怎么做:

def shareholder_title_sort(s1, s2):
    if s1.is_president: return -1
    elif s2.is_president: return 1
    elif s1.is_vice_president: return -1
    elif s2.is_vice_president: return 1
    elif s1.is_secretary: return -1
    elif s2.is_secretary: return 1
    elif s1.is_treasurer: return -1
    elif s2.is_treasurer: return 1
    else: return 0


并像这样使用它:

sorted(list(shareholders), cmp=shareholder_title_sort)


这是Shareholder类:

SHAREHOLDER_TITLE = (
    ("P", "President",),
    ("S", "Secretary",),
    ("T", "Treasurer",),
    ("V", "Vice President",),
)

class Shareholder(AuditModel):
    name = models.CharField(max_length=255)
    primary_title = models.CharField(max_length=1, choices=SHAREHOLDER_TITLE)
    secondary_title = models.CharField(max_length=1, choices=SHAREHOLDER_TITLE)

    @property
    def is_president(self):
        return self.primary_title == 'P' or self.secondary_title == 'P'

    @property
    def is_vice_president(self):
        return self.primary_title == 'V' or self.secondary_title == 'V'

    @property
    def is_secretary(self):
        return self.primary_title == 'S' or self.secondary_title == 'S'

    @property
    def is_treasurer(self):
        return self.primary_title == 'T' or self.secondary_title == 'T'


在Python 2中,有什么更优雅的方法可以做到这一点?

最佳答案

将类型映射为数字,并使用key排序:

def sort_by_role(s):
    if s.is_president: return 0
    if s.is_vice_president: return 1
    if s.is_secretary: return 2
    if s.is_treasurer: return 3
    return 4  # sort the rest at the end.

sorted(shareholders, key=sort_by_role)


如果存在“角色”属性,则可以在字典映射中使用它,但是:

role_order = {r[0]: i for i, r in enumerate(SHAREHOLDER_TITLE)}
best_role = lambda s: min(role_order[s.primary_rank], role_order[s.secondary_rank])
sorted(shareholders, key=best_role)


字典理解产生从排名字母到索引的映射(因此P映射到0)。 best_role根据其主要或次要角色找到股东的“最高”排名(最低指数)。

这确实假定您的SHAREHOLDER_TITLE序列按首选项顺序排序。如果没有,只需生成一个手动映射即可。例如{'P': 0, 'V': 1, 'S': 2, 'T': 3}

10-07 15:42