【问题标题】:Iterate through lists of lists and single elements遍历列表和单个元素的列表
【发布时间】:2020-08-26 09:38:03
【问题描述】:

鉴于以下列表,

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

我想了解它的所有元素。如您所见,当子集只有一个元素时,我没有 1 的列表,而只有元素。所以这当然行不通,因为a 的第二个元素是不可迭代的,

for x in a:
    for i in x:
        print(i)
        #do much more

错误:

   for i in x:

TypeError: 'int' object is not iterable

我可以做以下,但是我觉得很不方便,因为我必须复制代码,或者在'#do much more部分调用一个函数。有什么想法吗?

for x in a:
    if type(x) is list:
        for i in x:
            print(i)
            #do much more
    else:
        print(x)
        #do much more (the same as above)

【问题讨论】:

  • “我觉得它不方便”——这就是为什么不要在数据结构中组合类型通常是个好主意。大多数语言都禁止它,仅仅因为 Python 允许它并不能使它成为问题的最佳解决方案。你想用这个数据结构实现什么?推荐阅读:xy problem。例如,如果你把你的数字做成单元素列表,那么检查类型的问题就从本质上解决了。
  • 您实际上可以暂时将其转换为str 并工作并将其转换回来吗? b = [str(i) for i in a]。希望它不包括任何数学,正如您在上面的 Q 中提到的那样,您需要它
  • @ggorlen 这只是一个小例子。我正在阅读巨大的json 文件,其结构使得在层次结构的某个点我有元素列表或单独一个元素(不在长度为 1 的列表中)。
  • 好吧,如果你采用这种方法,我想你会发现无论你想在哪里有意义地使用数据(不清楚你所做的只是打印,还是这是基础一些大型应用程序或什么),您将需要编写条件来确定您手头的类型,然后再对其进行操作。你的整个代码库可能会被这样的重复类型检查弄得一团糟,所以我建议重新评估这个数据结构是否是你真正想要使用的。回答者只是向您展示了处理相同基本设计缺陷的各种方法。
  • @ggorlen 事实上,我不只是打印,这就是为什么我写了做更多的事情,我想保持这个想法简单,同时说明我做的不仅仅是打印。总的来说,我同意你的看法,这不是一个好习惯,但现在我只需要稍作修改即可完成此操作。我也同意大多数答案只是一种解决方法,实际上很多只是我一开始就有的解决方案,但是看看 M. Abreu 的,这看起来很通用。

标签: python list


【解决方案1】:

问题是你有一个集合,其中每个元素都可以是一个集合或单个元素。如果您想避免扁平化,并且来自@green-cloak-guy 的扁平化输出不适合您的使用,您可以在使用之前整理数据,以便您可以将其作为有保证的列表列表使用。

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

for x in a:
    if not isinstance(x, list):
        x = [x]
    for i in x:
        print(i)
        #do much more

说真的,我不懂 python,但那应该可以帮到你。

附言说真的,我不知道python。你只需拿起东西,我在 REPL 中运行它来验证它。

【讨论】:

  • 这是唯一能正确识别设计缺陷并提供修复结构的方法的答案。我会永久改变列表以始终将单元素列表包含为a = [x if isinstance(x, list) else [x] for x in a],然后继续愉快地在可预测的结构上进行迭代,但这可以让您很好地到达正确的区域。
【解决方案2】:

一种不需要类型检查并避免重复自己的“pythonic”方法是使用所谓的 EAFP(“请求宽恕比请求许可更容易” ) 编码风格(见my answer另一个问题 了解更多详情)。

下面是如何将它应用到这个场景中:

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

for x in a:
    try:
        it = iter(x)
    except TypeError:
        it = [x]
    for i in it:
        print(i)
        #do much more

【讨论】:

    【解决方案3】:

    您可以通过定义一个返回生成器的函数来将您的附加逻辑移出循环:

    def flatten(items):
        for item in items:
            if isinstance(item, list):
                yield from flatten(item)
            else:
                yield item
    
    a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]
    
    for i in flatten(a):
        print(i)
        # Your logic here!
    

    你可以验证上面代码的输出:

    1
    2
    3
    1
    1
    2
    43
    5
    1
    23
    4
    4
    6.5
    1
    1
    2
    45
    

    【讨论】:

      【解决方案4】:

      编写一个递归函数来为你做这件事:

      def print_my_list(lst):
          for elem in lst:
              if type(elem) is list:
                  print_my_list(elem)
              else:
                  print(elem)
      

      一件好事是,这将适用于彼此嵌套的任意数量的列表,将它们全部“展平”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-13
        • 1970-01-01
        • 2013-04-08
        • 2011-02-10
        • 2018-03-14
        • 2018-07-11
        相关资源
        最近更新 更多