提问人:kakuro 提问时间:4/4/2023 最后编辑:Yash Mehtakakuro 更新时间:4/4/2023 访问量:181
卡在这个功能上
Stuck on this function
问:
def moves_to_nested_dict(moves: list[list[str]]) -> dict[tuple[str, int], dict]:
"""
Convert <games> into a nested dictionary representing the sequence of moves
made in the games.
Each list in <games> corresponds to one game, with the i'th str being the
i'th move of the game.
The nested dictionary's keys are tuples containing the string representing
the move made on that turn and an integer indicating how many games ended
immediately after this move. See the docstring example below.
The values of each nested dictionary are themselves nested dictionaries of
this structure. An empty dictionary is stored as the value for a move that
will correspond to a leaf
Note: to keep the docstring short, we use single letters in place
of real chess moves, as it has no impact on the logic of how this
code needs to be implemented, since it should work for arbitary
strings used to denote moves.
>>> moves_to_nested_dict([[]]) # empty lists are ignored
{}
>>> moves_to_nested_dict([])
{}
>>> moves_to_nested_dict([['a'], []])
{('a', 1): {}}
>>> d = moves_to_nested_dict([["a", "b", "c"],
... ["a", "b"], ["d", "e"], ["d", "e"]])
>>> d
{('a', 0): {('b', 1): {('c', 1): {}}}, ('d', 0): {('e', 2): {}}}
>>> d = moves_to_nested_dict([
... ["a", "b", "c"], ["a", "b"], ["d", "e", "a"], ["d", "e"]])
>>> d
{('a', 0): {('b', 1): {('c', 1): {}}}, ('d', 0): {('e', 1): {('a', 1): {}}}}
"""
我一直在尝试解决这个功能,但我有点卡住了。我知道如何编写一般结构,但不知道如何正确获取数字。有人可以帮忙实施吗?
这是我所做的:
result = {}
for game_moves in moves:
if len(game_moves) == 0:
continue
current_dict = result
num_ended_games = 0
for move in game_moves[:-1]:
key = (move, num_ended_games)
if key not in current_dict:
current_dict[key] = {}
current_dict = current_dict[key]
num_ended_games = 0
last_move = game_moves[-1]
key = (last_move, num_ended_games)
if key not in current_dict:
current_dict[key] = {}
current_dict = current_dict[key]
num_ended_games += 1
return result
错误消息是
失败的例子:
d
预期:
{('a', 0): {('b', 1): {('c', 1): {}}}, ('d', 0): {('e', 2): {}}}
有:
{('a', 0): {('b', 0): {('c', 0): {}}}, ('d', 0): {('e', 0): {}}}
答:
1赞
Driftr95
4/4/2023
#1
您使用嵌套的 for 循环走在正确的轨道上,但是
num_ended_games = 0 ## beginning of loop
key = (move, num_ended_games) if key not in current_dict:
num_ended_games += 1 ## end of loop
在循环结束时递增而不将其设置在任何地方不会在字典中更新它。若要更改字典键,需要将旧值设置为新键,然后对旧键进行 del
或 .pop
。另外,请记住,元组在 python 中是不可变的,因此要更改元组中的一个值,您需要替换整个元组......num_ended_games
result
尝试类似于以下版本的版本。(查看示例输出)moves_to_nested_dict
def moves_to_nested_dict(moves: list[list[str]]) -> dict[tuple[str,int], dict]:
result = {}
for game_moves in moves:
cur_dict = result
for reverse_index, move in enumerate(game_moves, 1-len(game_moves)):
cur_key = [k for k in cur_dict if k[0]==move]
if not cur_key: cur_dict[(cur_key := (move, 0))] = {}
else: cur_key = cur_key[0]
if not reverse_index: ## <-- reverse_index=0 on last move
cur_dict[(move, cur_key[1]+1)] = cur_dict.pop(cur_key)
else: cur_dict = cur_dict[cur_key]
return result
[使用带有 start=1-len
的枚举
使reverse_index
计数从 1-len
开始,到 0 结束 - 因此我们可以使用它来跟踪还剩下多少步以及我们何时进行最后一次移动;而 walrus 运算符 (:=
) 只是在一个语句中定义/更新和使用变量的便捷方法,而不是在使用它之前需要额外的行来设置它。
顺便说一句,如果字典中的值可以用作键,这将简单得多,并且您可以只使用 .setdefault
,而不需要检查和有时更新键:num_ended_games
move
def moves_to_nested_dict(moves: list[list[str]]) -> dict[str,dict]:
result = {}
for game in moves:
cur_dict = result
for move in game:
cur_dict = cur_dict.setdefault(move, {'__games_ended__':0}) # (move,{})
if game: cur_dict['__games_ended__'] = cur_dict.get('__games_ended__',0)+1
return result
[当您无法确定密钥是否存在时,使用 <dict>.get(
<key>) 比 <dict>[<key>]
更安全。
有了这个版本,
moves_to_nested_dict([['a','b'], ['a','b'], ['a','b','c'], ['d','a'], ['a','d']])
会回来的
{ 'a': { '__games_ended__': 0, 'b': {'__games_ended__': 2, 'c': {'__games_ended__': 1}}, 'd': {'__games_ended__': 1} }, 'd': {'__games_ended__': 0, 'a': {'__games_ended__': 1}} }
评论