如何在Python中按职务排序

如何在Python中按职务排序,python,python-2.7,sorting,Python,Python 2.7,Sorting,我有一个名为股东的类,每个股东可以有4个职位中的一个:总裁、副总裁、秘书或司库(按顺序排列) 我想按职务对股东名单进行排序,但我不知道如何进行排序,只知道这样做: 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_pr

我有一个名为
股东
的类,每个
股东
可以有4个职位中的一个:总裁、副总裁、秘书或司库(按顺序排列)

我想按职务对股东名单进行排序,但我不知道如何进行排序,只知道这样做:

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_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'

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

将类型映射到数字,在
键中使用该键进行排序:

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
根据股东的主要或次要角色查找其“最高”排名(最低指数)


这确实假设您的
股东\u头衔
序列按优先顺序排序。如果没有,只需制作一个手动映射;e、 g.
{'P':0,'V':1,'S':2,'T':3}

将类型映射到数字,在

键中使用该键进行排序:

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
根据股东的主要或次要角色查找其“最高”排名(最低指数)


这确实假设您的
股东\u头衔
序列按优先顺序排序。如果没有,只需制作一个手动映射;e、 g.
{P':0,'V':1,'S':2,'T':3}

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

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
TITLES={'President':'P','secondpresident':'V',
‘秘书’:‘S’,‘司库’:‘T’}
选项=TITLES.items()中a、b的元组((b,a))
类别股东(审计模式):
name=models.CharField(最大长度=255)
主标题=models.CharField(最大长度=1,选项=选项)
次要标题=models.CharField(最大长度=1,选项=选项)
定义初始化(self,*args,**kwargs):
super()
@财产
def是大学校长(自我):
返回自我。有头衔(“总裁”)
@财产
def是副总裁(自我):
返回自我。有头衔(“副总裁”)
@财产
国防部秘书(自我):
返回自我。有头衔(“秘书”)
@财产
def是财务主管(自我):
返回自我。有头衔(“司库”)
def__有_标题(self,title):
返回{self.primary_title,self.secondary_title}中的标题[title]
定义(自身、其他):
返回自己的订单<其他订单
@财产
定义顺序(自):
如果赛尔夫是大学校长:
返回0
如果self.u是副总裁:
返回1
如果self.is_秘书:
返回2
如果self.u是司库:
返回3
返回4

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

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
TITLES={'President':'P','secondpresident':'V',
‘秘书’:‘S’,‘司库’:‘T’}
选项=TITLES.items()中a、b的元组((b,a))
类别股东(审计模式):
name=models.CharField(最大长度=255)
主标题=models.CharField(最大长度=1,选项=选项)
次要标题=models.CharField(最大长度=1,选项=选项)
定义初始化(self,*args,**kwargs):
super()
@财产
def是大学校长(自我):
返回自我。有头衔(“总裁”)
@财产
def是副总裁(自我):
返回自我。有头衔(“副总裁”)
@财产
国防部秘书(自我):
返回自我。有头衔(“秘书”)
@财产
def是财务主管(自我):
返回自我。有头衔(“司库”)
def__有_标题(self,title):
返回{self.primary_title,self.secondary_title}中的标题[title]
定义(自身、其他):
返回自己的订单<其他订单
@财产
定义顺序(自):
如果赛尔夫是大学校长:
返回0
如果self.u是副总裁:
返回1
如果self.is_秘书:
返回2
如果self.u是司库:
返回3
返回4

我认为优雅的方法是不使用布尔表示标题,而是使用带有字符串值的“title”属性。那么股东只需要一个财产,而不是工作岗位那么多,我们确实需要。问题是我们使用了两个属性:
primary\u title
secondary\u title
,以及
is{title}
是抽象掉其主要或次要标题的属性。希望这能有所帮助。@grantmconnaughey:您仍然可以使用映射:
min(role\u order[s.primary\u title],role\u order[s.secondary\u title])
将按照它们的最高级别角色对它们进行排序。我认为最好的方法是不使用布尔值来表示标题,而是使用带有字符串值的“title”属性。那么股东只需要一个财产,而不是工作岗位那么多,我们确实需要。问题是我们使用了两个属性:
primary\u title
secondary\u title
,以及
is{title}
是抽象掉其主要或次要标题的属性。希望这能有所帮助。@grantmcconnaughey:您仍然可以使用映射:
min(角色\u顺序[s.prima