如何将list(list(tuple))转换为list(set(tuple))解决unhashable类型报错
报错原因
- 触发
TypeError: unhashable type的核心原因是:原有代码生成的单副手牌是list类型,列表属于可变对象,本身不可哈希,无法被存入集合;同时原有递归逻辑全程生成嵌套列表结构,和要求的list[set[tuple]]目标结构不匹配。 - 定义的类型别名
Hand = set[tuple[str, str]]要求单个手牌为存储卡牌元组的集合,但原有代码的递归终止条件、元素拼接逻辑都是基于列表实现,完全没有用到集合类型。
无依赖修复方案
不需要导入任何模块,只需要修改all_matches函数的两处逻辑即可:
- 递归终止条件(
num == 0时),将原来返回的空列表[[]]改为返回空集合[set()],对齐集合类型的手牌结构。 - 替换原来的列表拼接逻辑,每次生成新手牌时新建集合副本,加入当前选中的卡牌,避免修改递归链路中复用的集合对象,最终得到的每个手牌都是合法的set结构。
修复后的完整可运行代码:
Hand = set[tuple[str, str]] def all_card(): # 52 cards rank: list[str] = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] suit: list[str] = ['Club', 'Diamond', 'Heart', 'Spade'] my_card = [] for i in rank: for j in suit: my_card.append((i, j)) return my_card def all_matches(cards, num): if num == 0: return [set()] L = [] for i in range(0, len(cards)): first = cards[i] rem = cards[i + 1:] all_comb = all_matches(rem, num - 1) for comb in all_comb: # 新建集合副本,避免修改原有递归结果 new_hand = set(comb) new_hand.add(first) L.append(new_hand) print(len(L)) return L def all_hands() -> list[Hand]: # 2,598,960 my_card = all_card() return all_matches(my_card, 5) print(all_hands())
验证说明
- 代码运行后会打印组合总数
2598960,和5张牌的德州扑克手牌总数完全一致。 - 最终返回结构为
list[set[tuple[str, str]]],符合要求的list(set(tuple))结构,集合内存储的卡牌元组为不可变类型,不会再触发不可哈希的报错。 - 全程未使用任何import语句,满足课程要求。
内容的提问来源于stack exchange,提问作者user19518892
相关产品推荐
相关产品推荐

