【问题标题】:Sorting a list with both numbers and letters用数字和字母对列表进行排序
【发布时间】:2021-04-04 13:56:43
【问题描述】:

我是一名一年级的 A-Level 学生,我正在尝试对下面的列表进行排序,这代表了纸牌游戏 Rummy 中的一手牌:

hand = [(1, '-', '3', 'Spades'), (2, '-', '8', 'Clubs'), (3, '-', '10', 'Hearts'), (4, '-', 'Ace', 'Spades'), (5, '-', '7', 'Clubs'), (6, '-', 'Queen', 'Diamonds'), (7, '-', '10', 'Spades')]

我希望它按字母顺序排序(梅花、梅花、方块、红心、黑桃、黑桃、黑桃),如果花色相同,则价值最低的牌(Ace 最低,King最高)首先出现。排序后,index[0] 值(在程序的其他部分中选择一张卡时只是为每张卡提供参考编号)应该基本上重新分配,以便它们再次按从 1 到 7 的顺序读取。我希望它输出如下:

[(1, '-', '7', 'Clubs'), (2, '-', '8', 'Clubs'), (3, '-', 'Queen', 'Diamonds'), (4, '-', '10', 'Hearts'), (5, '-', 'Ace', 'Spades'), (6, '-', '3', 'Spades'), (7, '-', '10', 'Spades')]

我想过尝试做这样的事情:

suit_hand = (hand[0][4], hand[1][4], hand[2][4], hand[3][4], hand[4][4], hand[5][4], hand[6][4])
arr = sorted(suit_hand)

然后对卡片值使用标准排序算法,可能是插入排序,但我不确定如何执行它。

任何帮助将不胜感激,谢谢。

【问题讨论】:

  • 这能回答你的问题吗? sorting list of cards
  • @HåkenLid 这个问题与我的问题类似,是的,不幸的是,答案对我来说有点复杂,我只是 A-Level 一年级的学生!

标签: python sorting


【解决方案1】:

试试这个:

hand = [(1, '-', '3', 'Spades'), (2, '-', '8', 'Clubs'), (3, '-', '10', 'Hearts'), (4, '-', 'Ace', 'Spades'),
        (5, '-', '7', 'Clubs'), (6, '-', 'Queen', 'Diamonds'), (7, '-', '10', 'Spades')]
print(sorted(hand, key=lambda x: x[3]))

输出

[(2, '-', '8', 'Clubs'), (5, '-', '7', 'Clubs'), (6, '-', 'Queen', 'Diamonds'), (3, '-', '10', 'Hearts'), (1, '-', '3', 'Spades'), (4, '-', 'Ace', 'Spades'), (7, '-', '10', 'Spades')]

【讨论】:

    【解决方案2】:

    您可以使用每张卡的值之间的映射 ('2': 2, ... 'Ace': 14) 来简化比较:

    value_rank = {
        **{'Jack': 11, 'Queen': 12, 'King': 13, 'Ace': 14},
        **{str(i): i for i in range(2, 11)}}
    
    sorted(hand, key=lambda c: (c[3], -value_rank[c[2]]))
    # out:
    [(2, '-', '8', 'Clubs'),
     (5, '-', '7', 'Clubs'),
     (6, '-', 'Queen', 'Diamonds'),
     (3, '-', '10', 'Hearts'),
     (4, '-', 'Ace', 'Spades'),
     (7, '-', '10', 'Spades'),
     (1, '-', '3', 'Spades')]
    

    哦,重新分配卡号:

    >>> [(i,) + c[1:] for i, c in enumerate(sorted(hand, key=lambda c: (c[3], -value_rank[c[2]])))]
    [(0, '-', '8', 'Clubs'),
     (1, '-', '7', 'Clubs'),
     (2, '-', 'Queen', 'Diamonds'),
     (3, '-', '10', 'Hearts'),
     (4, '-', 'Ace', 'Spades'),
     (5, '-', '10', 'Spades'),
     (6, '-', '3', 'Spades')]
    

    但是请注意,如果您花一点时间定义一个 card 类(一个简单的 namedtuple 和一些 total_ordering),您将获得更多可用的代码:

    @total_ordering
    class card(namedtuple('Card', 'cid dash value suit')):
        def __eq__(self, other):
            return (self.suit, self.value) == (o.suit, o.value)
        
        def __lt__(self, o):
            return (self.suit, -value_rank[self.value]) < (o.suit, -value_rank[o.value])
        
        def with_id(self, cid):
            return card(cid, self.dash, self.value, self.suit)
    
    hand = [card(*c) for c in hand]
    [c.with_id(i) for i, c in enumerate(sorted(hand))]
    # out:
    [card(cid=0, dash='-', value='8', suit='Clubs'),
     card(cid=1, dash='-', value='7', suit='Clubs'),
     card(cid=2, dash='-', value='Queen', suit='Diamonds'),
     card(cid=3, dash='-', value='10', suit='Hearts'),
     card(cid=4, dash='-', value='Ace', suit='Spades'),
     card(cid=5, dash='-', value='10', suit='Spades'),
     card(cid=6, dash='-', value='3', suit='Spades')]
    

    【讨论】:

    • 太棒了!很好的答案!
    • 我将使用有序列表和索引values = [*range(1,11),'Jack', 'Queen', 'King','Ace']lambda c: (c[3], -values.index(c[2])),而不是声明字典
    • @adirabargil:谢谢,但是在列表中查找索引是O(n),而在字典中查找值是O(1)
    • 当您谈论列出 14 的大小时,它并不那么严重......
    猜你喜欢
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多