如何实现先按卡牌类型再按卡牌值对Python卡牌列表排序?
问题描述
需要实现先按卡牌类型、再按卡牌值对卡牌列表排序,预期示例:2 clubs , 3 clubs , 6 clubs , 5 heart, 10 heart……。尝试使用lambda函数作为sorted的key但未得到预期结果,请求帮助。
现有代码如下:
from enum import Enum import random type=Enum('type','Heart Diamond Club Spade') value=Enum('value','2 3 4 5 6 7 8 9 10 J Q K A') class Card(): def __init__(self,type,value) : self.card_type=type self.card_value=value def __str__(self) : txt=str(self.card_value.name)+' '+str(self.card_type.name) return txt def __eq__(self, __o: object) -> bool: if self.card_type==__o.card_type and self.card_value==__o.card_value: return True else: return False def __lt__(self,__o:object) -> bool: if self.card_type==__o.card_type and int(self.card_value.value)<int(__o.card_value.value): return True else: return False def __gt__(self,__o:object) -> bool: if self.card_type==__o.card_type and int(self.card_value.value)>int(__o.card_value.value): return True else: return False def deal(deck,cardNum): cardlist=list() for i in range(cardNum): c=random.choice(deck) deck.remove(c) cardlist.append(c) #sorted(cardlist,key=lambda ) # My problem is here :( return cardlist
解决方案
问题出在两个核心点:一是Card类的比较方法(__lt__/__gt__)仅处理同类型卡牌的比较,不同类型时无排序逻辑;二是sorted函数未正确设置排序规则。下面提供两种修复方式:
方式一:修复Card类的比较方法
让__lt__方法先比较卡牌类型的枚举值,再比较卡牌值的枚举值,Python内置排序会自动依据该逻辑完成排序:
def __lt__(self, __o: object) -> bool: # 先按类型排序,类型相同时按卡牌值排序 if self.card_type.value != __o.card_type.value: return self.card_type.value < __o.card_type.value return self.card_value.value < __o.card_value.value
无需单独实现__gt__,Python会自动通过__lt__推导反向比较逻辑。
修改后在deal函数中直接调用sorted:
cardlist = sorted(cardlist)
方式二:使用sorted的key参数(无需修改类方法)
如果不想改动Card类的原有逻辑,可直接给sorted指定元组类型的key——元组首元素为卡牌类型枚举值,次元素为卡牌值枚举值,排序时会先按类型、再按值排序:
cardlist = sorted(cardlist, key=lambda card: (card.card_type.value, card.card_value.value))
完整优化代码示例
以下是结合方式一的完整代码,同时将type/value改为CardType/CardValue避免与Python内置函数名冲突:
from enum import Enum import random CardType = Enum('CardType', 'Heart Diamond Club Spade') CardValue = Enum('CardValue', '2 3 4 5 6 7 8 9 10 J Q K A') class Card(): def __init__(self, card_type, card_value): self.card_type = card_type self.card_value = card_value def __str__(self): return f"{self.card_value.name} {self.card_type.name}" def __eq__(self, __o: object) -> bool: return self.card_type == __o.card_type and self.card_value == __o.card_value def __lt__(self, __o: object) -> bool: if self.card_type.value != __o.card_type.value: return self.card_type.value < __o.card_type.value return self.card_value.value < __o.card_value.value def deal(deck, card_num): card_list = [] for _ in range(card_num): card = random.choice(deck) deck.remove(card) card_list.append(card) # 执行排序 card_list = sorted(card_list) return card_list # 测试功能 if __name__ == "__main__": # 生成完整牌堆 full_deck = [Card(ctype, cval) for ctype in CardType for cval in CardValue] # 发10张牌并排序 dealt_cards = deal(full_deck, 10) # 打印结果 for card in dealt_cards: print(card)
内容的提问来源于stack exchange,提问作者Stefano
相关产品推荐
相关产品推荐

