【问题标题】:Index all *except* one item in python在python中索引所有*除了*一项
【发布时间】:2013-10-17 16:12:39
【问题描述】:

有没有一种简单的方法来索引列表(或数组,或其他)的所有元素除了特定索引?例如,

  • mylist[3] 将返回位置 3 中的项目

  • milist[~3] 将返回除 3 之外的整个列表

【问题讨论】:

    标签: python list numpy indexing


    【解决方案1】:

    使用np.delete !它实际上并没有就地删除任何东西

    在您的示例中,“mylist[~3]”会这样写:mylist.delete(3)

    一个更复杂的例子:

    import numpy as np
    a = np.array([[1,4],[5,7],[3,1]])                                       
     
    # a: array([[1, 4],
    #           [5, 7],
    #           [3, 1]])
    
    ind = np.array([0,1])                                                   
    
    # ind: array([0, 1])
    
    # a[ind]: array([[1, 4],
    #                [5, 7]])
    
    all_except_index = np.delete(a, ind, axis=0)                                              
    # all_except_index: array([[3, 1]])
    
    # a: (still the same): array([[1, 4],
    #                             [5, 7],
    #                             [3, 1]])
    

    【讨论】:

      【解决方案2】:
      arr=[1,3,5,7,9]
      for i in range(len(arr)):
          arsum = arr[:i] + arr[i + 1:]
      

      【讨论】:

        【解决方案3】:

        我找到的最简单的方法是:

        mylist[:x] + mylist[x+1:]
        

        这将产生您的mylist,而没有索引x处的元素。

        示例

        mylist = [0, 1, 2, 3, 4, 5]
        x = 3
        mylist[:x] + mylist[x+1:]
        

        产生的结果

        mylist = [0, 1, 2, 4, 5]
        

        【讨论】:

        • 我发现这实际上删除了 x+1 项,但仍然有用,谢谢
        • @JackTC 它不应该
        • Python 在基本操作的情况下似乎已经过时了
        • exc = lambda s, i: s[:i] + s[i+1:] exc(mylist, 3) [0, 1, 2, 4, 5]
        • 如果 x==5,会引发 IndexError
        【解决方案4】:

        如果你想剪掉最后一个或第一个,这样做:

        list = ["This", "is", "a", "list"]
        listnolast = list[:-1]
        listnofirst = list[1:]
        
        

        如果您将 1 更改为 2,前 2 个字符将被删除,而不是第二个。 希望这仍然有帮助!

        【讨论】:

          【解决方案5】:

          请注意,如果变量是列表列表,则某些方法会失败。 例如:

          v1 = [[range(3)] for x in range(4)]
          v2 = v1[:3]+v1[4:] # this fails
          v2
          

          对于一般情况,使用

          removed_index = 1
          v1 = [[range(3)] for x in range(4)]
          v2 = [x for i,x in enumerate(v1) if x!=removed_index]
          v2
          

          【讨论】:

            【解决方案6】:

            我将提供一种功能性(不可变)的方式。

            1. 标准且简单的方法是使用切片:

              index_to_remove = 3
              data = [*range(5)]
              new_data = data[:index_to_remove] + data[index_to_remove + 1:]
              
              print(f"data: {data}, new_data: {new_data}")
              

              输出:

              data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
              
            2. 使用列表理解:

              data = [*range(5)]
              new_data = [v for i, v in enumerate(data) if i != index_to_remove]
              
              print(f"data: {data}, new_data: {new_data}") 
              

              输出:

              data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
              
            3. 使用过滤功能:

              index_to_remove = 3
              data = [*range(5)]
              new_data = [*filter(lambda i: i != index_to_remove, data)]
              

              输出:

              data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
              
            4. 使用遮罩。屏蔽由标准库中的itertools.compress 函数提供:

              from itertools import compress
              
              index_to_remove = 3
              data = [*range(5)]
              mask = [1] * len(data)
              mask[index_to_remove] = 0
              new_data = [*compress(data, mask)]
              
              print(f"data: {data}, mask: {mask}, new_data: {new_data}")
              

              输出:

              data: [0, 1, 2, 3, 4], mask: [1, 1, 1, 0, 1], new_data: [0, 1, 2, 4]
              
            5. 使用 Python 标准库中的 itertools.filterfalse 函数

              from itertools import filterfalse
              
              index_to_remove = 3
              data = [*range(5)]
              new_data = [*filterfalse(lambda i: i == index_to_remove, data)]
              
              print(f"data: {data}, new_data: {new_data}")
              

              输出:

              data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
              

            【讨论】:

              【解决方案7】:

              如果你事先不知道索引,这里有一个可以工作的函数

              def reverse_index(l, index):
                  try:
                      l.pop(index)
                      return l
                  except IndexError:
                      return False
              

              【讨论】:

                【解决方案8】:

                对于列表,您可以使用列表组合。例如,要使 b 成为不带第三个元素的 a 的副本:

                a = range(10)[::-1]                       # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
                b = [x for i,x in enumerate(a) if i!=3]   # [9, 8, 7, 5, 4, 3, 2, 1, 0]
                

                这是非常通用的,可用于所有可迭代对象,包括 numpy 数组。如果将[] 替换为()b 将是一个迭代器而不是一个列表。

                或者您可以使用 pop 就地执行此操作:

                a = range(10)[::-1]     # a = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
                a.pop(3)                # a = [9, 8, 7, 5, 4, 3, 2, 1, 0]
                

                numpy 中,您可以使用布尔索引来做到这一点:

                a = np.arange(9, -1, -1)     # a = array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
                b = a[np.arange(len(a))!=3]  # b = array([9, 8, 7, 5, 4, 3, 2, 1, 0])
                

                一般来说,这比上面列出的列表理解要快得多。

                【讨论】:

                  【解决方案9】:
                  >>> l = range(1,10)
                  >>> l
                  [1, 2, 3, 4, 5, 6, 7, 8, 9]
                  >>> l[:2] 
                  [1, 2]
                  >>> l[3:]
                  [4, 5, 6, 7, 8, 9]
                  >>> l[:2] + l[3:]
                  [1, 2, 4, 5, 6, 7, 8, 9]
                  >>> 
                  

                  另见

                  Explain Python's slice notation

                  【讨论】:

                  • 列表的好答案。你也可以将它用于数组,但你需要使用numpy.concatenate
                  【解决方案10】:

                  如果你使用的是numpy,我能想到的最接近的是使用掩码

                  >>> import numpy as np
                  >>> arr = np.arange(1,10)
                  >>> mask = np.ones(arr.shape,dtype=bool)
                  >>> mask[5]=0
                  >>> arr[mask]
                  array([1, 2, 3, 4, 5, 7, 8, 9])
                  

                  使用itertools 而不使用numpy 可以实现类似的效果

                  >>> from itertools import compress
                  >>> arr = range(1,10)
                  >>> mask = [1]*len(arr)
                  >>> mask[5]=0
                  >>> list(compress(arr,mask))
                  [1, 2, 3, 4, 5, 7, 8, 9]
                  

                  【讨论】:

                  • 我可能会使用np.arange(len(arr)) != 3 之类的东西作为掩码,因为这样它可以被内联,例如arr[~(np.arange(len(arr)) == 3)] 或其他。
                  • @DSM:请将此作为答案发布:-)。无论如何,我对 Numpy 不太熟悉。
                  • +1 用于屏蔽数组,如果是列表,我会使用切片并使用压缩连接。
                  猜你喜欢
                  • 2020-11-12
                  • 2020-02-02
                  • 2015-02-27
                  • 1970-01-01
                  • 2019-03-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-06-07
                  相关资源
                  最近更新 更多