【问题标题】:Finding lowest value within a nested list?在嵌套列表中找到最低值?
【发布时间】:2015-01-31 11:08:15
【问题描述】:

我正在尝试编写一个函数,该函数接受一个列表并可以打印该列表中的最小整数。现在我试图弄清楚在嵌套列表的情况下该做什么,如果最小的数字在这些嵌套列表之一内,那么总体上它将打印该数字。我的代码在这里:

def listMin():
list2 = [3,4,[2,99,8],7]

for i in range (len(list2)):
    if type(list2[i]) == type([]):



        y=min(i)
        list2.append(y)
        print "hello"
    if len(list2)== 0:
        return None
    else:


        x= min(list2)
        print x


listMin()

虽然这似乎应该打印数字 2,但它没有打印,并且一旦到达嵌套列表就会给我一个错误:

TypeError: 'int' object is not iterable

我尝试了多种方法,但我很难理解为什么这种方法不起作用。

【问题讨论】:

    标签: python list int nested iterable


    【解决方案1】:

    嵌套一深

    在您的示例中,列表仅嵌套一层。如果是这种情况,请尝试:

    >>> list2 = [3,4,[2,99,8],7]
    >>> min(x if isinstance(x, int) else min(x) for x in list2)
    2
    

    任意深度的嵌套

    如果允许更深的嵌套,定义这个递归函数:

    >>> def rmin(lst): return min(x if isinstance(x, int) else rmin(x) for x in lst)
    ... 
    

    运行中:

    >>> rmin(list2)
    2
    

    或者,使用更深的嵌套:

    >>> list3 = [3,4,[[2,99],8],7]
    >>> rmin(list3)
    2
    >>> list4 = [3, 4, [[2, [99, 1]], 8], 7]
    >>> rmin(list4)
    1
    

    工作原理

    函数rmin由单行组成:

    return min(x if isinstance(x, int) else rmin(x) for x in lst)
    

    如您所见,这是一个列表推导式,它查看列表 lst 的每个值 x

    让我们将min 的参数分成两部分。第一个是:

    x if isinstance(x, int) else rmin(x)
    

    如果x 是整数,则返回x。否则,它会在x 上调用rmin。在后一种情况下,rmin 递归查看x 中的每个值并返回最小值。

    min的第二部分参数是:

    for x in lst
    

    这只是列表理解的常用方法。它依次提取lst中的每个值并将其分配给x

    【讨论】:

      【解决方案2】:

      一般来说,您可以展平列表并在展平的列表中搜索 min。有很多扁平化的食谱。这是我从here 获取的。

      import collections
      
      def flatten(iterable):
          for el in iterable:
              if isinstance(el, collections.Iterable) and not isinstance(el, str): 
                  yield from flatten(el)
              else:
                  yield el
      
      list2 = [3,4,[2,99,8],7]
      
      print(list(flatten(list2)))
      # [3, 4, 2, 99, 8, 7]
      print(min(flatten(list2)))   
      # 2
      

      这也适用于多个嵌套列表,例如:

      list2 = [3,4,[2,99,8,[-1,-2]],7]
      
      print(list(flatten(list2)))
      # [3, 4, 2, 99, 8, -1, -2, 7]
      print(min(flatten(list2)))  
      # -2 
      

      【讨论】:

        【解决方案3】:

        问题是线路引起的

        y=min(i)
        

        其中i 是一个整数,但不是一个列表。你可能想要y = min(list2[i])

        请注意,虽然您已将此 y 附加回原始列表,但循环不会到达新添加的元素,因为 i 的范围只能达到列表的原始长度。

        通过一些简单的 Python 习语,你的原始想法可以用更易读的方式表达如下:

        def listMin():
            lst = [3,4,[2,99,8],7]
            for x in lst:
                if type(x) == list:
                    lst.append(min(x))
            print min(lst)
        
        
        listMin()
        

        【讨论】:

        • 是的,但它不会只是该语句中的一个列表,因为 if 语句是如果原始列表中该元素的类型是一个列表,那么找到该列表的最小值并将其附加到 list2?
        • list2[i] 是该声明中的列表,是的;但i 仍然是整数索引。
        【解决方案4】:

        当我需要做类似的事情时,我写了以下内容:

        import copy
        
        def nestedMin(list_):
          target_list = copy.deepcopy(list_)  # to keep original list unchanged
          for index in range (len(target_list)):
            if type (target_list[index]) is list:
              target_list[index] = nestedMin(target_list[index])
        
          return min(target_list)
        

        我知道效率不高,一直在做deepcopy;但它是可读的,它可以完成工作:)

        例子:

        list1 = [2,3,[4, -5, [7, -20]]]
        print nestedMin(list1) # prints -20
        print list1  # prints [2, 3, [4, -5, [7, -20]]]
        

        【讨论】:

          猜你喜欢
          • 2021-02-24
          • 1970-01-01
          • 2021-01-13
          • 2011-06-15
          • 1970-01-01
          • 2020-10-30
          • 2018-08-18
          • 1970-01-01
          相关资源
          最近更新 更多