【问题标题】:Python cut array into two arrays using indices arrayPython使用索引数组将数组切割成两个数组
【发布时间】:2018-01-05 15:11:53
【问题描述】:

我有一个数组,假设 arr = [1, 2, 3, 4, 5, 6, 7, 8] 和另一个索引数组:idx = [0, 3, 4, 6]

我想得到两个数组,一个只是来自 arr 的那些索引: [1, 4, 5, 7] 剩下的就是另一个:[2, 3, 6, 8]

有人可以帮我吗?我只能想到丑陋的方法来做到这一点,但它必须是一些优雅地做到这一点的功能。

非常感谢!

【问题讨论】:

    标签: python arrays


    【解决方案1】:

    你可以这样做:

    selected = [arr[i] for i in idx]
    other = [v for i, v in enumerate(arr) if i not in idx]
    

    如果arr 没有重复,你也可以这样做:

    other = [v for v in arr if v not in selected]
    

    【讨论】:

    • 效果很好。非常感谢!
    【解决方案2】:

    方法:

    a1 = [arr[x] for x in idx] 
    a2 = [x for x in arr if x not in a1]
    

    【讨论】:

      【解决方案3】:

      一次遍历:

      no, yes = both = [], []
      for i, x in enumerate(arr):
          both[i in idx].append(x)
      

      或者(由 Chris_Rands 评论):

      yes, no = [], []
      for i, x in enumerate(arr):
          (yes if i in idx else no).append(x)
      

      虽然idx 应该要么很小,要么变成一个集合(其他答案中的解决方案也是如此,我猜他们只是不想谈论它)。

      演示:

      >>> if 1:
          arr = [1, 2, 3, 4, 5, 6, 7, 8]
          idx = [0, 3, 4, 6]
          no, yes = both = [], []
          for i, x in enumerate(arr):
              both[i in idx].append(x)
          print('yes', yes)
          print('no', no)
      
      yes [1, 4, 5, 7]
      no [2, 3, 6, 8]
      

      【讨论】:

      • @Chris_Rands 嗯,如果我将 both 重命名为 noyesno_yes 会怎样?
      • 嗯,我想这是主观的,但我个人更喜欢另一种方式,而且它可能对初学者来说不太容易混淆
      • @Chris_Rands 好的,我会添加它。我认为我开始使用我的一个原因是它更快,但我只是再次计时并且它更慢。谢谢。
      【解决方案4】:

      numpy 有一个巧妙的解决方案:

      import numpy as np
      
      arr = np.asarray([1, 2, 3, 4, 5, 6, 7, 8])  # converts your list in numpy array
      idx1 = [0, 3, 4, 6]
      idx2 = [1, 2, 5, 7]
      
      arr1 = arr[idx1]  # [1 4 5 7]
      arr2 = arr[idx2]  # [2 3 6 8]
      

      【讨论】:

        【解决方案5】:

        您可以使用itertools 进行单行解决方案:

        import itertools
        arr = [1, 2, 3, 4, 5, 6, 7, 8]
        idx = [0, 3, 4, 6]
        [(out_index, not_in_arr), (in_index, in_arr)] = [(a, list(b)) for a, b in itertools.groupby(sorted(arr, key=lambda x:arr.index(x) in idx), key=lambda x:arr.index(x) in idx)]
        print(not_in_arr)
        print(in_arr)
        

        输出:

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

        【讨论】:

          【解决方案6】:

          您还可以将arr 中的每个值映射到字典,指示它的索引是否存在于idx

          arr = [1, 2, 3, 4, 5, 6, 7, 8]
          idx = [0, 3, 4, 6]
          
          # converted to a set
          idx_lookup = set(idx)
          
          d = {x: True if i in idx_lookup else False for i, x in enumerate(arr)}
          print(d)
          

          这给出了这个字典:

          {1: True, 2: False, 3: False, 4: True, 5: True, 6: False, 7: True, 8: False}
          

          我还将idx 转换为集合,因为在这种情况下,不需要重复索引,集合/字典查找是O(1)。但是,列表查找是O(n),所以如果可能的话,这种优化是值得的。

          一旦你有了这本字典,你就可以filter取出你想保留的元素,其余的元素从此:

          keep = list(filter(lambda x: d[x], arr))
          rest = list(filter(lambda x: not d[x], arr))
          
          print(keep)
          print(rest)
          

          哪些输出:

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

          注意:您还可以在keeprest 的过滤上方使用列表推导:

          keep = [x for x in arr if d[x]]
          rest = [x for x in arr if not d[x]]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-11-18
            • 2019-05-02
            • 2022-01-09
            • 2017-06-24
            • 2018-01-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多