Python:在最右边嵌套列表的末尾添加一个值

时间:2011-04-26 19:13:33

标签: python list recursion

我正在尝试做的是,给定一个包含任意数量的其他嵌套列表的列表,递归地下降嵌套列表中的最后一个值,直到我达到最大深度,然后附加一个值那份清单。一个例子可能会使这更清楚:

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

5 个答案:

答案 0 :(得分:4)

这个怎么样:

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

答案 1 :(得分: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)

答案 2 :(得分:1)

这是我的看法:

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's的递归方案相同,但处理空列表。
  • 我不认为这两种类型测试有很好的方法,但是你接近它们(例如使用'type'或检查'append'......)。

答案 3 :(得分:0)

您可以测试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测试有点烦人,但另一种方法是将引用传递给父级和子级。

答案 4 :(得分:0)

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)