【问题标题】:Remove any empty list present in the list删除列表中存在的任何空列表
【发布时间】:2021-08-15 08:48:08
【问题描述】:

我有一个清单:

i = [[1,2,3,[]],[],[],[],[4,5,[],7]]

我想删除所有的空列表:

[[1,2,3],[4,5,7]]

我该怎么做?

这是我的代码:

res = [ele for ele in i if ele != []]

【问题讨论】:

  • print([[j for j in ele if j] for ele in i if ele]) ?
  • 成功了。谢谢!!
  • 这只有在你确定你的数组是二维的时候才会起作用。如果维度比较多或者外层数组有非数组元素,就会失败。
  • @MuslimbekAbduganiev 查看我对更多维度数组的回答

标签: python list list-comprehension


【解决方案1】:

使用递归函数从列表中删除空列表。
使用递归,您可以将空列表删除到任何深度:

def remove_nested_list(listt):
    for index, value in enumerate(reversed(listt)):
        if isinstance(value, list) and value != []:
            remove_nested_list(value)
        elif isinstance(value, list) and len(value) == 0:
            listt.remove(value)


a = [[1, 2, 3, 0, []], [], [], [], [4, 5, [], 7]]
print(f"before-->{a}")
remove_nested_list(a)
print(f"after-->{a}")

输出:

before-->[[1, 2, 3, 0, []], [], [], [], [4, 5, [], 7]]
after-->[[1, 2, 3, 0], [4, 5, 7]]

【讨论】:

  • if not value: 输入为零。
  • 不使用索引为什么还要枚举?
  • 另一个有趣的考虑是如何处理[[]]。看起来您的代码将删除内部空列表,留下[]。我不知道这是否会是理想的结果。
  • @Teepeemm 不错的边缘案例。我想我们需要两个递归函数,一个用于检查它是否为空嵌套列表,第二个用于删除它们。
  • 另外,你为什么要倒序遍历列表?
【解决方案2】:

你可以使用列表推导(实际上是嵌套推导):

i = [[1, 2, 3, []], [], [], [], [4, 5, [], 7]]

res = [[sub_item for sub_item in item if sub_item != []] for item in i if item != []]
print(res)

我们检查空列表两次,一次检查i 中的容器列表和if item != [],另一次检查这些容器中的单个元素,使用if sub_item != []

【讨论】:

  • if itemif item != [] 更像 Pythonic。虽然这是假设 item 始终是一个可能为空的列表,而不是像 0 或 None 这样可能是 Falsey 的其他东西。
  • @Teepeemm 完全正确。
【解决方案3】:

您还可以通过过滤“无值”来删除空列表。

尝试:

i = 过滤器(无,i)

【讨论】:

    【解决方案4】:

    我会使用一些不会改变原始列表的方法。

    第一个简单地删除列表中的所有空列表,而不是嵌套:

    def remove_empty_lists(lst):
        return [ e for e in lst if not (isinstance(e, list) and len(e)==0) ]
    

    第二种方法只是以递归方式使用前者:

    def deep_remove_empty_lists(lst):
        lst = remove_empty_lists(lst)
        return [ deep_remove_empty_lists(e) if isinstance(e, list) else e for e in lst ]
    

    所以,在提交的案例中:

    i = [[1,2,3,[]],[],[],[],[4,5,[],7]]
    deep_remove_empty_lists(i)
    
    #=> [[1, 2, 3], [4, 5, 7]]
    

    或者在最深的嵌套情况下:

    ii = [[1,2,3,[]],[],[],[],[4,5,[],7,[8, 9, [], [10, 11, []]]]]
    deep_remove_empty_lists(ii)
    
    #=> [[1, 2, 3], [4, 5, 7, [8, 9, [10, 11]]]]
    

    【讨论】:

      【解决方案5】:

      如果嵌套总是两层深,即在你的问题中,一个干净的方法是:

      >>> not_empty_list = lambda value: value != []
      
      ## Above is equivalent to:
      #  not_empty_list = [].__ne__
      #  not_empty_list = functools.partial(operator.ne, []))
      
      >>> result = [
              list(filter(not_empty_list, inner_list))
              for inner_list in i 
              if not_empty_list(inner_list)
          ]
      >>> result
      [[1, 2, 3], [4, 5, 7]]
      

      处理像[]这样的列表:

      >>> i
      [[1, 2, 3, []], [], [], [], [4, 5, [], 7], [[]]]
      
      >>> result = [
              list(filter(not_empty_list, inner_list))
              for inner_list in i 
              if not_empty_list(inner_list)
          ]
      >>> list(filter(not_empty_list, result))
      [[1, 2, 3], [4, 5, 7]]
      

      【讨论】:

        【解决方案6】:

        从任意嵌套列表中删除空列表。我们可以在这里使用递归。 这是一个简单的方法。我们需要遍历列表并检查元素是否为空列表。如果是,那么我们不会将其添加到最终列表中。如果不是空列表,我们重复上述过程。

        def remove_empty(lst):
            return (
                [remove_empty(i) for i in lst if i!=[]]
                if isinstance(lst, list)
                else lst
            )
        

        输出:

        i = [[1, 2, 3, []], [], [], [], [4, 5, [], 7]]
        print(remove_empty(i))
        # [[1, 2, 3], [4, 5, 7]]
        
        # Example taken from iGian's answer 
        ii = [[1, 2, 3, []], [], [], [], [4, 5, [], 7, [8, 9, [], [10, 11, []]]]] 
        print(remove_empty(ii))
        # [[1, 2, 3], [4, 5, 7, [8, 9, [10, 11]]]]
        

        要检查一个对象是否可迭代,我们使用collection.abc.iterable

        from collections.abc import Iterable
        all(
            isinstance(i, Iterable)
            for i in ([], tuple(), set(), dict(), range(10), (_ for _ in range(10)))
        )
        # True
        

        现在,您可以将 isinstance(lst, list) 替换为 isinstance(lst, Iterable) 以从每个可迭代对象中过滤掉空列表,即 []

        编辑:

        @Teepeemm 指出了一个绝妙的极端案例,所有答案都错过了。

        为了解决这个问题,我们需要两个递归函数,一个用于检查它是否为空嵌套列表,第二个用于删除空嵌套列表

        def empty(lst):
            if lst == []:
                return True
            elif isinstance(lst, list):
                return all(empty(i) for i in lst)
            else:
                return False
        
        def remove_empty(lst):
            return (
                [remove_empty(i) for i in lst if not empty(i)]
                if isinstance(lst, list)
                else lst
            )
        
        i = [[1, 2, 3, [[]]]] 
        remove_empty(i)
        # [[1, 2, 3]]
        remove_nested_list(i) # Muhammad Safwan's answer
        print(i) # [[1, 2, 3, []]]
        
        ii = [[1, 2, 3, [[], [[[[], []]]]]]]
        remove_empty(ii)
        # [[1, 2, 3]]
        remove_nested_list(ii) # Muhammad Safwan's answer
        print(ii) # [[1, 2, 3, [[[[]]]]]]
        

        【讨论】:

          【解决方案7】:

          如果您需要能够处理任意深度嵌套的列表,并且还想删除例如[[]][[], [[], []]] 或其他仅包含空列表的列表(列表仅包含)空列表,这是一个简单的递归解决方案:

          def simplify(value):
            if isinstance(value, list):
              return [y for y in (simplify(x) for x in value) if y != []]
            else:
              return value
          
          print(simplify([[1,2,3,[]],[],[],[],[4,5,[],7],[[],[[]]],[[],[8]]]))
          

          Try it online!

          此解决方案与迄今为止发布的大多数(全部?)其他递归解决方案之间的主要区别在于它首先递归地简化它遇到的任何子列表,然后然后跳过任何简化后为空的子列表。这也是允许它跳过 [[]] 等子列表的原因。

          (但是请注意,如果给定一个列表,此函数仍将始终返回一个列表,即使该列表可能为空。例如,simplify([[], [[]]]) 仍将返回[],而不是None . 如果你想对简化后顶层列表为空的情况做一些特殊处理,你需要单独检查。但至少在通过上面的函数运行列表之后,你可以检查仅使用例如if simplified_list == []:.)

          【讨论】:

            【解决方案8】:

            从列表中删除空列表

            我们可以使用列表推导方法来解决这个问题。

            你可以参考下面的代码

            # Initialize list =>
            list_1 = [11,20,5,[],7,12,3,[],[],23]
            
            # print list 
            print("Original List: "+ str(list_1))
            
            # remove empty list using list comprehension
            output = [ i for i in list_1 if i!=[] ] 
            
            # print output
            print("list after empty list removed: " + str(output))
            

            输出:

            原始列表:[11, 20, 5, [ ], 7, 12, 3, [ ], [ ], 23]

            删除空列表后的列表:[11, 20, 5, 7, 12, 3, 23]

            【讨论】:

            • 这与问题中发布的半解决方案相同,并没有解决嵌套列表的问题
            【解决方案9】:

            简单的递归解决方案

            a = [[1,2,3,[]],[],[],[],[4,5,[],7]]
            
            def nested_check(alist):
                for item in alist[:]:
                    if item == []:
                        alist.remove(item)
                    elif isinstance(item, list):
                        nested_check(item)
            
            nested_check(a)
            print(a)
            

            输出:

            [[1, 2, 3], [4, 5, 7]]
            

            【讨论】:

              【解决方案10】:

              只有当您在另一个列表中最多有一个列表时,它才会起作用。 [1,2,[1,2],3] 随着更多的列表相互嵌套,您只需要添加更多的循环。

              a = [[1, 2, 3, 0, []], [], [], [], [4, 5, [], 7]]
              print('list before:', a)
              while [] in a:
                  for i in a:
                      if i == []:
                          a.remove(i)
              for i in a:
                  for e in i:
                      if e == []:
                          i.remove(e)
              print('list after:', a)
              

              这就是我得到的结果:

              list before: [[1, 2, 3, 0, []], [], [], [], [4, 5, [], 7]]
              list after: [[1, 2, 3, 0], [4, 5, 7]]
              

              【讨论】:

                猜你喜欢
                • 2016-06-18
                • 1970-01-01
                • 2020-07-05
                • 2014-01-06
                • 1970-01-01
                • 2015-09-20
                • 2017-11-02
                • 2022-11-01
                • 2013-01-15
                相关资源
                最近更新 更多