【问题标题】:Unhashable Type "Dict" [duplicate]不可散列的类型“字典”[重复]
【发布时间】:2015-11-03 02:09:06
【问题描述】:

我正在编写一个基本的 uno 类型的纸牌游戏,并且希望能够(同时为玩家制作 7 张牌)检查该值是否已经在玩家的牌组中(我使用随机)。我得到了一个不可散列的 dict 错误,其他一些问题是关于相同的错误,但在代码的不同部分。不管怎样,这是我的代码。

def CardGame():

    nm=8
    clist=["Red","Blue","Green","Yellow"]
    nlist=[]
    for i in range(0,10):
     nlist.append(i)
    pd={}
    deck={"Red":0,"Red":1,"Red":2,"Red":3,"Red":4,"Red":5,"Red":6,"Red":7,"Red":8,"Red":9,"Blue":0,"Blue":1,"Blue":2,"Blue":3,"Blue":4,"Blue":5,"Blue":6,"Blue":7,"Blue":8,"Blue":9,"Green":0,"Green":1,"Green":2,"Green":3,"Green":4,"Green":5,"Green":6,"Green":7,"Green":8,"Green":9,"Yellow":0,"Yellow":1,"Yellow":2,"Yellow":3,"Yellow":4,"Yellow":5,"Yellow":6,"Yellow":7,"Yellow":8,"Yellow":9}
    for i in range(1,nm):
     c=random.choice(clist)
     d=random.choice(nlist)
     if ({c:d}) in deck:
      pd.update({c:d})
      del deck[c:d]
     else:
      nm=nm+1
  print("%s %s"%(c,d))

【问题讨论】:

  • 与您的错误不完全相关,但在创建后立即尝试print(deck),您可能会惊讶地看到它有多少条目。
  • 哦,我看到最后一个条目是如何覆盖其他条目的;有没有办法解决这个问题?
  • 你为什么使用随机来检查一个值是否在牌组中?似乎您应该遍历所有组合。
  • @Rutvik:您的字典键在所有卡片中必须是唯一的。你的价值观并不重要(你真的不需要字典;一套就可以了)。您可以将您的密钥形成为,例如,“R0”、“B8”等。
  • @RutvikMarathe 您可以使用元组列表:[("Red", 0), ("Red", 1)] 或字符串列表:["Red0", "Red1"]。在字典中,每个键只能有一个对应的值。换句话说,deck["Red"] 只能返回一个值。 More on dictionaries here

标签: python


【解决方案1】:

使用if ({c:d}) in deck:,您正在检查字典{c:d} 是否作为字典deck 中的键存在。字典是不可散列的(可变数据类型通常是这样),并且字典键必须是可散列的,因此与其只是告诉您“不”,它会抛出您看到的错误。字典永远不会作为键出现在字典中。

此外,如 cmets 中所述,字典键是唯一的,因此您创建的字典不能像它出现的那样存在。考虑一个不同的数据结构,例如tuples 中的list(例如[('Red', 1), ('Red', 2),...),或者带有list 值的字典(例如{'Red':[1, 2, 3,...], 'Blue':[1, 2, 3,...],...})。

【讨论】:

    【解决方案2】:

    您的具体错误来自您尝试在字典中检查会员船的方式。 in 运算符检查是否存在给定键,但您传递的是单元素字典,而不仅仅是一个键(您会得到特定的异常,因为字典不是有效的键,因为它们不能被散列)。

    但是,正如 Kevin 上面评论的那样,您还有一个更大的问题,即您的 deck 字典不包含您希望它包含的内容,因为您重复使用相同的键。对于给定的键,字典只能有一个值(尽管该值可以是列表或元组,或包含其他项目的其他类型)。

    有多种方法可以解决此问题。包含 2 元组的 set 的工作方式类似于您希望 dict 工作的方式。您可以使用addremove 元素,并使用in 运算符有效地检查元组是否在集合中。

    但是,看看您实际在做什么,我认为对您的算法进行更大的更改会好得多。与其随机选择颜色和数字然后检查它是否仍在您的deck 中,不如直接从集合中选择一个随机元素。与其循环选择多个值,不如使用random.sample 一次选择所有值。或者,如果您稍后要从牌组中获取更多随机值,请shuffle 并从中分一杯羹。

    这是一个在 2 元组列表上使用 random.shuffle 的代码版本,然后从末尾切掉其中的 10 个以成为 pd 列表。

    import itertools
    import random
    
    def CardGame():
        nm=8
        clist = ["Red","Blue","Green","Yellow"]
        nlist = list(range(0,10)) # this is easier than looping to append the values
        deck = list(itertools.product(clist, nlist)) # much easier than naming them all
        random.shuffle(deck)
        pd = deck[-10:] # slice 10 items from the end
        del deck[-10:] # and then remove them from the list (fairly efficient at the end)
    

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 2019-08-29
      • 1970-01-01
      • 2012-01-21
      • 2019-01-07
      • 2016-01-11
      • 2023-03-06
      相关资源
      最近更新 更多