【问题标题】:Why is sort() function not properly working with the integers in this list?为什么 sort() 函数不能正确处理此列表中的整数?
【发布时间】:2022-01-02 05:20:40
【问题描述】:

我正在尝试创建一副牌,将其洗牌,然后重新排序。

问题是当我在洗牌后对其进行排序时,列表最终是这样的:[10, 11, 12, 13, 8, 9]

例如,我使用了一个较小的牌组。有了完整的套牌,列表仍然会结束:[10, 11, 12, 13, 1, 2, ...]

为什么列表没有正确排序?

这是我的代码:

import random

# Initialize Deck
deck = []
suits = ['Club', 'Spade', 'Heart', 'Diamond']

for i in range(8, 14):
    for s in range(4):
        deck.append([str(i), suits[s]])

# Format numbers into card face
for i in range(len(deck)):
    if deck[i][0] == "1":
        deck[i][0] = "Ace"
    elif deck[i][0] == "11":
        deck[i][0] = "J"
    elif deck[i][0] == "12":
        deck[i][0] = "Q"
    elif deck[i][0] == "13":
        deck[i][0] = "K"

print("Initial deck", deck)
print()

# Shuffle Deck
random.shuffle(deck)
print("Shuffle function:", deck)

# Turn face back to number for sorting
for i in range(len(deck)):
    if deck[i][0] == "Ace":
        deck[i][0] = "1"
    elif deck[i][0] == "J":
        deck[i][0] = "11"
    elif deck[i][0] == "Q":
        deck[i][0] = "12"
    elif deck[i][0] == "K":
        deck[i][0] = "13"
        
deck.sort()
print("Sort function: ", deck)

输出:

Initial deck: [['8', 'Club'], ['8', 'Spade'], ['8', 'Heart'], ['8', 'Diamond'], ['9', 'Club'], ['9', 'Spade'], ['9', 'Heart'], ['9', 'Diamond'], ['10', 'Club'], ['10', 'Spade'], ['10', 'Heart'], ['10', 'Diamond'], ['J', 'Club'], ['J', 'Spade'], ['J', 'Heart'], ['J', 'Diamond'], ['Q', 'Club'], ['Q', 'Spade'], ['Q', 'Heart'], ['Q', 'Diamond'], ['K', 'Club'], ['K', 'Spade'], ['K', 'Heart'], ['K', 'Diamond']]

Shuffle function: [['J', 'Heart'], ['8', 'Club'], ['Q', 'Spade'], ['9', 'Diamond'], ['9', 'Heart'], ['10', 'Diamond'], ['K', 'Heart'], ['K', 'Spade'], ['10', 'Heart'], ['9', 'Club'], ['8', 'Heart'], ['K', 'Club'], ['8', 'Diamond'], ['Q', 'Diamond'], ['9', 'Spade'], ['Q', 'Heart'], ['10', 'Spade'], ['K', 'Diamond'], ['J', 'Diamond'], ['Q', 'Club'], ['10', 'Club'], ['8', 'Spade'], ['J', 'Spade'], ['J', 'Club']]

Sort function:  [['10', 'Club'], ['10', 'Diamond'], ['10', 'Heart'], ['10', 'Spade'], ['11', 'Club'], ['11', 'Diamond'], ['11', 'Heart'], ['11', 'Spade'], ['12', 'Club'], ['12', 'Diamond'], ['12', 'Heart'], ['12', 'Spade'], ['13', 'Club'], ['13', 'Diamond'], ['13', 'Heart'], ['13', 'Spade'], ['8', 'Club'], ['8', 'Diamond'], ['8', 'Heart'], ['8', 'Spade'], ['9', 'Club'], ['9', 'Diamond'], ['9', 'Heart'], ['9', 'Spade']]

【问题讨论】:

  • 这叫自然排序,使用字母值进行排序。当你比较整数时,10 > 2 但是当你比较字符串时,'10' < '2' 因为字符 '1' 在字符 '2' 之前
  • 把整数放在你的列表中,而不是它们的字符串表示,这样可以正常工作
  • 不是来回转换,而是存储整数值,并具有将它们转换为字符串以进行打印的函数。或者使用 Enum 类型,它或多或少会自动执行此操作。

标签: python arrays sorting


【解决方案1】:

这是因为列表中的值是列表,而这些列表包含字符串。试试这样的:

import random

# Initialize Deck
deck = []
suits = ['Club', 'Spade', 'Heart', 'Diamond']

for i in range(8, 14):
    for s in range(4):
        deck.append([i, suits[s]])

# Format numbers into card face
for i in range(len(deck)):
    if deck[i][0] == 1:
        deck[i][0] = "Ace"
    elif deck[i][0] == 11:
        deck[i][0] = "J"
    elif deck[i][0] == 12:
        deck[i][0] = "Q"
    elif deck[i][0] == 13:
        deck[i][0] = "K"

print("Initial deck", deck)
print()

# Shuffle Deck
random.shuffle(deck)
print("Shuffle function:", deck)

# Turn face back to number for sorting
for i in deck:
    if deck[i][0] == "Ace":
        deck[i][0] = 1
    elif deck[i][0] == "J":
        deck[i][0] = 11
    elif deck[i][0] == "Q":
        deck[i][0] = 12
    elif deck[i][0] == "K":
        deck[i][0] = 13
        
deck.sort(key=lambda x:return x[0])
print("Sort function: ", deck)

【讨论】:

    【解决方案2】:

    您希望排名是int 值(而不是它们的str 版本),以便可以比较它们以进行排序。来回翻转它们以进行打印/分类是很多不必要的工作;我建议使用__repr__ 方法定义一个对象类,该方法可以按照您想要的方式格式化它们。

    import random
    
    
    class Card:
        def __init__(self, rank: int, suit: str):
            self.rank = rank
            self.suit = suit
    
        def __repr__(self) -> str:
            rank_names = {
                1: "Ace",
                11: "J",
                12: "Q",
                13: "K",
            }
            return f"[{rank_names.get(self.rank, self.rank)} {self.suit}]"
    
    
    deck = [
        Card(rank, suit) 
        for rank in range(8, 14) 
        for suit in ['Club', 'Spade', 'Heart', 'Diamond']
    ]
    
    print("Initial deck", deck, "\n")
    
    random.shuffle(deck)
    print("Shuffled deck:", deck, "\n")
    
    deck.sort(key=lambda card: (card.rank, card.suit))
    print("Sorted deck:", deck)
    

    打印:

    Initial deck [[8 Club], [8 Spade], [8 Heart], [8 Diamond], [9 Club], [9 Spade], [9 Heart], [9 Diamond], [10 Club], [10 Spade], [10 Heart], [10 Diamond], [J Club], [J Spade], [J Heart], [J Diamond], [Q Club], [Q Spade], [Q Heart], [Q Diamond], [K Club], [K Spade], [K Heart], [K Diamond]]
    
    Shuffled deck: [[K Heart], [10 Club], [9 Diamond], [8 Diamond], [10 Spade], [J Spade], [K Spade], [J Heart], [9 Spade], [10 Heart], [K Club], [10 Diamond], [Q Club], [K Diamond], [Q Spade], [J Diamond], [Q Diamond], [J Club], [9 Club], [8 Club], [9 Heart], [8 Heart], [Q Heart], [8 Spade]]
    
    Sorted deck: [[8 Club], [8 Diamond], [8 Heart], [8 Spade], [9 Club], [9 Diamond], [9 Heart], [9 Spade], [10 Club], [10 Diamond], [10 Heart], [10 Spade], [J Club], [J Diamond], [J Heart], [J Spade], [Q Club], [Q Diamond], [Q Heart], [Q Spade], [K Club], [K Diamond], [K Heart], [K Spade]]
    

    【讨论】:

      【解决方案3】:

      您应该使用整数而不是字符串作为数值。我还建议您用元组替换两个元素的内部列表(更多的风格选择):

      [(8, 'Club'), (8, 'Spade'), ...]
      

      如果您坚持使用字符串,那么您可以在排序函数中添加key 参数。它接受一个在比较之前映射您的对象的函数。在你的情况下:

      deck.sort(key=lambda x: int(x[0]))
      

      获取列表中的每个元素并将该元素的第一个成员转换为整数。

      另一个建议,使用字典而不是 if else 来映射数字和卡面,如下所示:

      # Dictionary instead of if/elif/else
      number_to_face = {
          "1": "Ace",
          "11": "J",
          "12": "Q",
          "13": "K"
      }
      

      这是一个完整的调整示例。

      import random
      
      # Initialize Deck
      deck = []
      suits = ['Club', 'Spade', 'Heart', 'Diamond']
      
      for i in range(8, 14):
          for s in range(4):
              deck.append((str(i), suits[s]))
      
      # Dictionary instead of if/elif/else
      number_to_face = {
          "1": "Ace",
          "11": "J",
          "12": "Q",
          "13": "K"
      }
      
      # Reverse mapping of key -> value to value -> key
      face_to_number = {v: k for k, v in number_to_face.items()}
      
      # Use list comprehension to update list
      def map_with(deck, mapping):
          return [(mapping.get(k, k), v) for k, v in deck]
      
      # Format numbers into card face
      deck = map_with(deck, number_to_face)
      
      print("Initial deck", deck)
      print()
      
      # Shuffle Deck
      random.shuffle(deck)
      print("Shuffle function:", deck)
      print()
      
      # Turn face back to number for sorting
      # Use list comprehension to update list
      deck = map_with(deck, face_to_number)
              
      deck.sort(key=lambda x: int(x[0]))
      print("Sort function: ", deck)
      

      【讨论】:

        猜你喜欢
        • 2015-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-22
        • 2019-05-21
        • 2015-05-17
        相关资源
        最近更新 更多