【问题标题】:Apply a function to each bottom elements in a list of lists将函数应用于列表列表中的每个底部元素
【发布时间】:2018-10-29 01:12:02
【问题描述】:

我有一些列表。每个列表的长度和深度以不可预测的方式变化。我想对每个底部元素应用一个函数。对于这个问题,我们可以说我只需要将每个 int 转换为 float。

我搜索了这个网站,发现了这个:Python: How to loop a list of lists of varying depth?

但是,当将此适应我的问题时,它成功地访问了每个元素,但似乎并没有转换实际值。最后,当我想要一个浮点列表时,我仍然有一个 int 列表。

def list_flatten(my_list):
    for item in my_list:
        if(isinstance(item,list)):
            list_flatten(item)
        else:
            item = float(item)
    return my_list

problem = [[[[1,1],[2,2],[3,3]],[[4,4],[5,5],[6,6]],[[7,7],[[8,8],[9,9]]]]]
print(list_flatten(problem))

【问题讨论】:

  • 您能告诉我们预期的输出吗?你只是想让这个:[[1,2], [3,6], [9,8]] 变成 [1.0, 2.0, 3.0, 6.0, 9.0, 8.0] 吗?
  • 您没有将浮动结果保存在任何地方
  • 如果你想在 python 上做得更好,你必须了解可变和不可变数据类型
  • 谢谢大家。我认为 item = float(item) 正在保存结果,但也许这不是可变的,正如其他评论员所说的那样。

标签: python


【解决方案1】:

那是因为,在以下方面:

for item in some_list:
    item = some_function(item)

.. 您只是将item 重新分配给一个新值。您没有更改列表中的实际元素。

您的代码中的另一个问题是您没有对 list_flatten(..) 递归调用返回的结果做任何事情。它不会神奇地放入结果数组中——您可能需要在列表对象上使用+= 运算符。

这是您的代码的工作版本:

def list_flatten(my_list):
    res = []
    for item in my_list:
        if isinstance(item,list):
            res += list_flatten(item)
        else:
            res.append(float(item))
    return res

【讨论】:

    【解决方案2】:

    您快到了,但原始列表项从未转换。考虑一下:

    def list_flatten(my_list_or_value):
        if isinstance(my_list_or_value,list):
            return [list_flatten(sublist) for sublist in my_list_or_value]
        return float(my_list_or_value)
    
    problem = [[[[1,1],[2,2],[3,3]],[[4,4],[5,5],[6,6]],[[7,7],[[8,8],[9,9]]]]]
    print(list_flatten(problem))
    

    -- 它遍历任何项目或子项目,如果您处于最深级别,则仅返回 float(x)

    【讨论】:

      【解决方案3】:

      这是一个适用于任何序列类型的版本。它将返回一个与旧序列具有相同类型的新序列:

      from collections.abc import Sequence
      
      def nested_convert(sequence, func):
          cls = type(sequence)
          return cls(nested_convert(subseq, func) if isinstance(subseq, Sequence) 
                                                  else func(subseq) for subseq in sequence)
      
      l = [((1, 2, 3), [5, 6, (2, 3)]), (3, 4, 5, [4, 5, 6])]
      print(nested_convert(l, lambda x: x*2))
      #   [((2, 4, 6), [10, 12, (4, 6)]), (6, 8, 10, [8, 10, 12])]
      

      【讨论】:

      • 为什么是lambda x: x*2? (出于这个问题的目的,我们可以说我只需要将每个 int 转换为 float。
      • 为什么不呢?它适用于任何可调用的单参数:nested_convert(l, float) 也可以正常工作。
      • 感谢您的回复!在尝试理解你的答案之前,我必须先理解更简单的答案:)
      【解决方案4】:

      您有正确的想法来遍历实际的整数元素,但似乎错过了理解如何修改它们。如果您是编程新手,欢迎学习“引用”与“值”的第一课。

      举个简单的例子:

      arr = [1,2,3,4]
      for el in arr:
          el = float(el)
          print el
      
      print arr
      
      # this will print
      1.0
      2.0
      3.0
      4.0
      [1,2,3,4]
      

      这是因为当您遍历列表时,变量 el 将采用 arr 中每个元素的“值”,而不是实际“引用”元素本身——您可以将其视为值所在的内存位置。因此,您对el 的修改是“有效的”,但仅限于el——数组中值的副本——而不是数组本身。

      如果我们把代码改成这样,你可以修改数组本身而不是局部变量el

      arr = [1,2,3,4]
      for i in range(len(arr)):
          arr[i] = float(arr[i])
          print arr[i]
      
      print arr
      
      # this will print
      1.0
      2.0
      3.0
      4.0
      [1.0,2.0,3.0,4.0]
      

      您可以通过谷歌搜索“按引用传递与按值传递”和“指针”等内容来查找有关此概念的更多信息。这可能有点令人困惑,特别是如果您只熟悉 python 并且以前没有见过/使用过 C/C++ ——这些语言非常明确地说明了这些差异并迫使您尽早了解它们。祝你好运:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-04
        • 2021-12-27
        相关资源
        最近更新 更多