【问题标题】:Python: add a value to the end of the inner-most right nested listPython:在最内层嵌套列表的末尾添加一个值
【发布时间】:2011-08-13 07:26:27
【问题描述】:

我想要做的是,给定一个包含任意数量的其他嵌套列表的列表,递归遍历嵌套列表中的最后一个值,直到达到最大深度,然后将一个值附加到那个清单。举个例子可能会更清楚:

>>> nested_list1 = [1, 2, 3, [4, 5, 6]]
>>> last_inner_append(nested_list1, 7)
[1, 2, 3, [4, 5, 6, 7]]

>>> nested_list2 = [1, 2, [3, 4], 5, 6]
>>> last_inner_append(nested_list2, 7)
[1, 2, [3, 4], 5, 6, 7]

以下代码有效,但对我来说似乎过于棘手:

def add_to_inner_last(nested, item):
    nest_levels = [nested]
    try:
        nest_levels.append(nested[-1])
    except IndexError:                    # The empty list case
        nested.append(item)
        return
    while type(nest_levels[-1]) == list:
        try:
            nest_levels.append(nest_levels[-1][-1])
        except IndexError:                 # The empty inner list case
            nest_levels[-1].append(item)
            return
    nest_levels[-2].append(item)
    return

我喜欢它的一些地方:

  • 有效
  • 它处理列表末尾的字符串情况,以及空列表的情况

我不喜欢它的一些地方:

  • 我必须检查对象的类型,因为字符串也是可索引的
  • 索引系统感觉太神奇了——我明天就看不懂了
  • 使用附加到引用列表会影响所有引用这一事实感觉非常聪明

我对此有一些一般性的问题:

  • 一开始还担心追加到nest_levels会占用空间,后来才发现这大概只是一个引用,并没有创建新的对象吧?
  • 此代码纯粹是产生副作用(它总是返回None)。我应该担心吗?

基本上,虽然这段代码有效(我认为......),但我想知道是否有更好的方法来做到这一点。更好我的意思是更清晰或更pythonic。可能有更明确的递归?我很难定义一个停止点或一种在不产生副作用的情况下执行此操作的方法。

编辑:

明确一点,这个方法还需要处理:

>>> last_inner_append([1,[2,[3,[4]]]], 5)
[1,[2,[3,[4,5]]]]

和:

>>> last_inner_append([1,[2,[3,[4,[]]]]], 5)
[1,[2,[3,[4,[5]]]]]

【问题讨论】:

    标签: python list recursion


    【解决方案1】:

    这个怎么样:

    def last_inner_append(x, y):
        try:
            if isinstance(x[-1], list):
                last_inner_append(x[-1], y)
                return x
        except IndexError:
            pass
        x.append(y)
        return x
    

    【讨论】:

    • 顺便说一句,一个小建议(有点神圣的东西):在继承的情况下应该使用 'isinstance',在检查对象类型的情况下使用 type(obj)。
    • 这很好,但它不处理 x 为空列表或最后最内层列表为空列表的情况...
    • 但是,如果你将整个东西包装在一个 try: except IndexError: 块中,它就可以正常工作。如果您编辑此内容以包含该内容,我会接受。
    【解决方案2】:

    这个函数返回最深的内部列表:

    def get_deepest_list(lst, depth = 0):
        deepest_list = lst
        max_depth = depth
    
        for li in lst:
            if type(li) == list:
                tmp_deepest_list, tmp_max_depth = get_deepest_list(li, depth + 1)
                if max_depth < tmp_max_depth: # change to <= to get the rightmost inner list
                    max_depth = tmp_max_depth
                    deepest_list = tmp_deepest_list
    
        return deepest_list, max_depth
    

    然后将其用作:

    def add_to_deepest_inner(lst, item):
        inner_lst, depth = get_deepest_list(lst)
        inner_lst.append(item)
    

    【讨论】:

      【解决方案3】:

      这是我的看法:

      def last_inner_append(cont, el):
          if type(cont) == list:
              if not len(cont) or type(cont[-1]) != list:
                  cont.append(el)
              else:
                  last_inner_append(cont[-1], el)
      
      • 我认为它很好,很清晰,并且通过了你的所有测试。
      • 也是纯副作用;如果你想改变这一点,我建议你使用 BasicWolf 的方法并创建一个“选择器”和一个“更新”函数,后者使用前者。
      • 它与 Phil H 的递归方案相同,但处理的是空列表。
      • 我认为这两种类型测试没有什么好的方法,但是您可以使用它们(例如,使用“类型”或检查“附加”...)。

      【讨论】:

        【解决方案4】:

        您可以测试append 是否可调用,而不是使用try/catch 和递归:

        def add_to_inner_last(nested, item):
            if callable(nested,append):
                if callable(nested[-1],append):
                    return add_to_inner_last(nested[-1],item)
                else:
                    nested.append(item)
                    return true
            else:
                return false
        

        必须有两个callable 测试有点烦人,但另一种方法是传递对父级和子级的引用。

        【讨论】:

          【解决方案5】:
          def last_inner_append(sequence, element):
              def helper(tmp, seq, elem=element):
                  if type(seq) != list:
                      tmp.append(elem)
                  elif len(seq):
                      helper(seq, seq[-1])
                  else:
                      seq.append(elem)
              helper(sequence, sequence)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-20
            • 1970-01-01
            • 2020-10-14
            • 1970-01-01
            相关资源
            最近更新 更多