【问题标题】:sorting list of cards卡片排序列表
【发布时间】:2016-09-07 20:44:27
【问题描述】:

我有两个列表:

card_candidates = ['9D', '9S', '3S', '0D']
card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A']

我希望能够根据第二个列表顺序对第一个列表进行排序。所以排序后的 card_candidates 应该是这样的:

sorted_candidates = ['3S', '9D', '9S', '0D']

'0' 就是 10 的值,只是想让所有卡片的长度相同。如果存在平局,例如“9D”和“9S”,则需要对字母进行排序。到目前为止,我刚刚这样做了:

sorted_candidates = []
for x, y in zip(card_candidates, card_order):
    sorted_candidates.append([x[0] for x in card_candidates])
return sorted(sorted_candidates)

我知道这甚至不是正确的,我只是不知道该怎么做。

【问题讨论】:

    标签: python sorting


    【解决方案1】:

    生成一个字典,将您的排序顺序字符映射到一个数字,我们将按这些排序:

    sort_map = {c: i for i, c in enumerate(card_order)}
    

    您现在可以使用此映射对您的卡片进行排序,包括打破平局的第二个字母:

    sorted_candidates = sorted(card_candidates,
                               key=lambda card: (sort_map[card[0]], card[1]))
    

    排序键获取每张卡片的第一个字符并将其转换为来自sort_map 字典的整数,然后通知sorted() 函数正确的排序顺序。如果出现平局(相同的牌面值),牌将按梅花、方块、红心、黑桃的顺序排列(假设您使用CH 表示梅花和红心)。

    预先创建映射使排序保持在 O(NlogN) 时间复杂度内;您可以对card_order.index(card[0]) 执行相同操作,但随后您调用list.index() 调用为每个排序的元素list.index 需要扫描列表,产生 O(KNlogN) 排序(其中K 是card_order 列表的长度)。

    演示:

    >>> card_candidates = ['9D', '9S', '3S', '0D']
    >>> card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A']
    >>> sort_map = {c: i for i, c in enumerate(card_order)}
    >>> sorted(card_candidates, key=lambda card: (sort_map[card[0]], card[1]))
    ['3S', '9D', '9S', '0D']
    >>> sorted(['9D', '9S', '9C', '9H'], key=lambda card: (sort_map[card[0]], card[1]))
    ['9C', '9D', '9H', '9S']
    

    【讨论】:

    • +1 用于复杂性分析。这里有很多与python中的卡片分类相关的问题,这个答案是最好的:)
    【解决方案2】:

    您不一定需要任何额外的数据结构,card_order 列表完全足以使用这个简单的单线对您的卡片进行排序:

    card_candidates = ['9D', '9S', '3S', '0D']
    card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A']
    
    sorted_cards = sorted(card_candidates, key=lambda c: (card_order.index(c[0]), c[1]))
    
    print(list(sorted_cards))
    

    输出:

    ['3S', '9D', '9S', '0D']
    

    See this code running on ideone.com

    请注意,每次您对任何卡片列表进行排序时,此方法都会为每张卡片扫描一次card_order 列表以进行排序。如果您只是在游戏开始时或什至每隔几秒钟对一副普通的纸牌进行排序,这没有问题。但是,如果您的代码大部分时间都在对大量卡片进行排序或对卡片进行排序,那么您可能更喜欢Martijn Pieters 的解决方案,它将card_order 列表转换为可以更快地扫描的字典。

    【讨论】:

    • 我创建的映射避免了list.indexcard_order 进行的全面扫描。
    • @MartijnPieters 是的,我必须同意。如果您必须对许多卡片进行排序并且必须经常对它们进行排序,那么使用您的方法更有效,因为在字典中查找哈希比使用 index 扫描列表中的项目要快。但如果它只在游戏开始时发生一次,这不会是时间关键的用例,那么这几毫秒应该不会产生影响。
    • 当然,但这是 Stack Overflow,您的答案中的代码将被复制并粘贴到任何地方。始终解释代码的权衡,以便少数阅读足够上下文的人能够理解。 :-) 在 CS 术语中,您生成了 O(KNlogN) 排序,我的仍然是 O(NlogN)
    • @MartijnPieters 我添加了一个解释(尽管我不明白如何找出那些大 O 符号)。现在好点了吗?
    • 好的,谢谢!至于大 O 符号,Python Wiki documents the time complexity of many operations; TimSort(Python 使用的排序算法)是 O(NlogN),但是对于输入列表中的每个元素,您最多扫描 card_order 中的 K 个元素,使得整个过程 O(KNlogN)。
    猜你喜欢
    • 2021-02-07
    • 2021-11-19
    • 2019-11-18
    • 1970-01-01
    • 2016-12-06
    • 2020-07-08
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    相关资源
    最近更新 更多