卡在这个功能上

Stuck on this function

提问人:kakuro 提问时间:4/4/2023 最后编辑:Yash Mehtakakuro 更新时间:4/4/2023 访问量:181

问:

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): {}}}
python-3.x 函数 字典 嵌套

评论

0赞 Michael Butscher 4/4/2023
(1) 正确设置代码格式。(2)找一个标题,以更好的方式描述问题。(3)更好地描述问题中的问题。会发生什么,应该发生什么?在问题中将错误消息(如果有)完全显示为格式正确的文本。
1赞 Joran Beasley 4/4/2023
请添加您的尝试...复制和粘贴这个家庭作业问题通常会导致被遗忘的反对票

答:

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_gamesresult

尝试类似于以下版本的版本。查看示例输出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_gamesmove

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}}
}