【问题标题】:Reusable code to iterate along different array dimensions可重复使用的代码沿不同的数组维度进行迭代
【发布时间】:2020-06-08 22:00:48
【问题描述】:

说,我有一个N维数组my_array[D1][D2]...[DN]

对于某个应用程序,例如敏感性分析,我需要固定一个点p=(d1, d2, ..., dN),并一次沿每个维度进行迭代。 产生的行为是

for x1 in range(0, D1):
    do_something(my_array[x1][d2][d3]...[dN])
for x2 in range(0, D2):
    do_something(my_array[d1][x2][d3]...[dN])
.
.
.
for xN in range(0, DN):
    do_something(my_array[d1][d2][d3]...[xN])

如您所见,这里有很多重复的代码。我怎样才能减少工作并写一些优雅的代码呢?

例如,有没有类似下面的代码生成方法?

for d in range(0, N):
    iterate along the (d+1)th dimension of my_array, denoting the element as x:
        do_something(x)

【问题讨论】:

  • 为什么用c 标记?
  • 在外面多写一个for循环,能满足你的需要吗?
  • @Odysseus 我使用标签“c”是因为我认为这是一个普遍的问题,它也发生在 c 中。
  • @PhungDuyPhong 是的,但是怎么做?如何遍历不同的索引位置?我梦想着for i in range(1,N): iterate through index position i of my_array: do_something()
  • 您可以使用 itertools 代替嵌套循环。请参考以下链接stackoverflow.com/questions/38362368/…

标签: python arrays list iteration


【解决方案1】:

您可以使用 numpy.take 并执行以下操作。浏览文档以供参考。

https://docs.scipy.org/doc/numpy/reference/generated/numpy.take.html

N = len(my_array)
for i in range(N):
  n = len(my_array(i))
  indices = p
  indices[i] = x[i]
  for j in range(n):
     do_something(np.take(my_array,indices))

【讨论】:

    【解决方案2】:

    我不明白 d1 d2 d3 是什么,但我想你可以这样做:

    def get_list_item_by_indexes_list(in_list, indexes_list):
        if len(indexes_list) <= 1:
            return in_list[indexes_list[0]]
        else:
            return get_list_item_by_indexes_list(in_list[indexes_list[0]], indexes_list[1:])
    
    def do_to_each_dimension(multi_list, func, dimensions_lens):
        d0_to_dN_list = [l - 1 for l in dimensions_lens] # I dont know what is it
        for dimension_index in range(0, len(dimensions_lens)):
            dimension_len = dimensions_lens[dimension_index]
            for x in range(0, dimension_len):
                curr_d0_to_dN_list = d0_to_dN_list.copy()
                curr_d0_to_dN_list[dimension_index] = x
                func(get_list_item_by_indexes_list(multi_list, curr_d0_to_dN_list))
    
    
    def do_something(n):
        print(n)
    
    dimensions_lens = [3, 5]
    my_array = [
        [1, 2, 3, 4, 5], 
        [6, 7, 8, 9, 10], 
        [11, 12, 13, 14, 15]
        ]
    
    do_to_each_dimension(my_array, do_something, dimensions_lens)
    

    输出:

    5  10  15  11  12  13  14  15
    

    此代码遍历二维数组的最后一列和最后一行。

    现在,遍历 3d 数组每个维度的最后一行:

    dimensions_lens = [2, 4, 3]
    my_array = [
        [
            [1, 2, 3], 
            [4, 5, 6], 
            [7, 8, 9], 
            [10, 11, 12]
            ], 
        [
            [13, 14, 15], 
            [16, 17, 18], 
            [19, 20, 21], 
            [22, 23, 24]
            ], 
        ]
    
    do_to_each_dimension(my_array, do_something, dimensions_lens)
    

    输出:

    12  24  15  18  21  24  22  23  24
    

    (注意:不要在此代码中使用零长度尺寸)

    【讨论】:

      【解决方案3】:

      您可能会弄乱数组访问 (my_arr[d1][d2]...[dN]) 和 eval 的字符串表示形式,然后再获得所需的值。这是相当“hacky”的,但它适用于具有任意维度的数组,并允许您在处理底层嵌套数组访问时将索引作为列表提供,从而实现干净的双 for 循环。

      def access_at(arr, point):
          # build 'arr[p1][p2]...[pN]'
          access_str = 'arr' + ''.join([f'[{p}]' for p in point])
          return eval(access_str)
      

      使用这种访​​问方法非常简单:

      p = [p1, ..., pN]
      D = [D1, ..., DN]
      for i in range(N):
          # deep copy p
          pt = p[:]
          for x in range(D[i]):
              pt[i] = x
              do_something(access_at(my_array, pt))
      

      【讨论】:

        猜你喜欢
        • 2016-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-13
        • 2020-02-03
        • 2013-09-13
        • 1970-01-01
        相关资源
        最近更新 更多