2011-04-26 33 views
4

我想要做的是,給定一個包含任意數量的其他嵌套列表的列表,通過嵌套列表中的最後一個值遞歸下降列表直到達到最大深度,然後將值附加到該列表。一個例子可以說明清楚:Python:爲最內層最右邊的嵌套列表的末尾添加一個值

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

回答

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 
+2

順便說一句,一個小建議(有點聖潔的東西):在繼承的情況下應該使用'isinstance',並在檢查對象的類型時使用type(obj)。 – 2011-04-26 19:30:24

+0

這很好,但它不處理x是空列表或最後一個最內部列表是空列表的情況...... – Wilduck 2011-04-26 19:36:48

+0

但是,如果將整個事件包裝在'try:'中, IndexError:'阻止它正常工作。如果你編輯這個來包含它,我會接受它。 – Wilduck 2011-04-26 19:40:44

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) 
+0

評論,而不是答案... – Benjamin 2011-04-26 19:47:13

+0

這是更好的:) – Benjamin 2011-04-27 20:22:37

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測試,但另一種方法是將引用傳遞給父代以及子代。

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) 
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的遞歸方案相同,但處理空列表。
  • 我不認爲有兩種類型測試的好方法,但是你可以接近它們(例如'type'或檢查'append'...)。
相關問題