如何在Python中按职称排序

时间:2016-01-08 15:49:50

标签: python python-2.7 sorting

我有一个名为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中执行此操作的更优雅方法是什么?

2 个答案:

答案 0 :(得分:4)

将类型映射到数字,使用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}

答案 1 :(得分:0)

如下所示的解决方案可能有所帮助。答案代码的目标是在不需要密钥的情况下使对象可排序。根据使用的排序机制,可能需要其他比较运算符。

TITLES = {'President': 'P', 'Vice President': 'V',
          'Secretary': 'S', 'Treasurer': 'T'}
CHOICES = tuple((b, a) for a, b in TITLES.items())


class Shareholder(AuditModel):

    name = models.CharField(max_length=255)
    primary_title = models.CharField(max_length=1, choices=CHOICES)
    secondary_title = models.CharField(max_length=1, choices=CHOICES)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    @property
    def is_president(self):
        return self.__has_title('President')

    @property
    def is_vice_president(self):
        return self.__has_title('Vice President')

    @property
    def is_secretary(self):
        return self.__has_title('Secretary')

    @property
    def is_treasurer(self):
        return self.__has_title('Treasurer')

    def __has_title(self, title):
        return TITLES[title] in {self.primary_title, self.secondary_title}

    def __lt__(self, other):
        return self.__order < other.__order

    @property
    def __order(self):
        if self.is_president:
            return 0
        if self.is_vice_president:
            return 1
        if self.is_secretary:
            return 2
        if self.is_treasurer:
            return 3
        return 4