如何从一维数组中确定相邻元素?

问题描述

我正在编写有限元分析代码,目前我有一维数组列出了元素密度值,如下所示:
x = np.ones(12) 其中索引是元素编号 0,1,2,...,10,11
绘制时的元素是这样的:

0 - 3 - 6 - 9
1 - 4 - 7 - 10
2 - 5 - 8 - 11

我设置了 x 和 y 方向的元素数量(对于这种情况,x 为 4,y 为 3),但是我很难确定环绕元素。我需要找到一种方法来确定围绕给定元素的 3、5 或 8 个元素。例如,如果我选择元素 0 周围的元素是 1,3,4 或者如果我选择元素 6 周围的元素是 3,4,7,9,10 或者如果我选择元素 7 周围的元素是 3,5,6,8,11...
这里的最终目标是输入一个半径,并根据它确定选定元素周围的元素编号。对此的任何建议或帮助将不胜感激。出于某种原因,我无法确定在 python 中执行此操作的逻辑。

解决方法

确定执行此操作的逻辑

  • 具有 6 个项目的一维数组具有索引 - [0,1,2,3,4,5]
  • 建议的形状为 2 行 3 列 - M,N = 2,3
  • 对于任何项目的索引 (i),其行和列都是 c,r = divmod(i,M)
  • 邻居列,行索引将是
    • cplus,cminus = c + 1,c - 1
      rplus,rminus = r + 1,r - 1
      cplus,r
      cminus,r
      c,rplus
      c,rminus
      cplus,rplus
      cplus,rminus
      cminus,rplus
      cminus,rminus
      
  • 那些 2d 索引需要使用 (col * M) + row 转换为 1d 索引

例如

[0,5]
M,3
'''
0  2  4
1  3  5
'''
  • item 4 的二维索引是 c,r = divmod(4,M) --> (2,0) (col,row)

  • 其邻居的二维索引之一是 c,rplus --> (2,1)

  • 那个邻居的一维索引是(2 * M) + 1 --> 5

  • 在将邻居的 2d 索引转换为 1d 后,您需要检查并丢弃一些没有意义的。

    • 第 4 项位于右上角的一个角落,并且没有像 c,rminus 这样的 (2,-1) 这样没有意义的邻居。或者 cplus,r ... (3,0) 这也没有意义。

警告 - 我没有尝试彻底测试这个。


这是一个返回可调用对象的函数。

import operator
def get_neighbors(index,shape=(M,N)):
    '''Returns a callable.

    (M,N) --> (number_of_rows,number_of_columns)
    '''
    M,N = shape
    # 2d index
    c,r = divmod(index,M)
    print(f'2d index: {(c,r)}')
    # neighbors
    cplus,c - 1
    rplus,r - 1
    # dot product of (c,cplus,cminus) and (r,rplus,rminus)?
    neighbors = [
        (cminus,rminus),(cminus,r),rplus),(c,(cplus,]
    # print(neighbors)

    # validate/filter
    neighbors = [
        (col,row) for col,row in neighbors if (0 <= col < N) and (0 <= row < M)
    ]
    # print(neighbors)

    # 1d indices
    one_d = [(col * M) + row for col,row in neighbors]
    # print(one_d)
    return operator.itemgetter(*one_d)

试试看。

>>> a = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t']

>>> M,N = 4,5    # nrows,ncols

'''
[['a' 'e' 'i' 'm' 'q']
 ['b' 'f' 'j' 'n' 'r']
 ['c' 'g' 'k' 'o' 's']
 ['d' 'h' 'l' 'p' 't']]
'''

>>> # i's neighbors
>>> q = get_neighbors(a.index('i'),(M,N))
2d index: (2,0)
>>> q(a)
('e','m')
>>>
>>> # k's neighbors
>>> q = get_neighbors(a.index('k'),2)
>>> q(a)
('f','j')
>>>
>>> # q's neighbors
>>> q = get_neighbors(a.index('q'),N))
2d index: (4,0)
>>> q(a)
('m','r')
>>>

i 不同形状的邻居

>>> M,N = 5,4
>>> q = get_neighbors(a.index('i'),N))
2d index: (1,3)
>>> q(a)
('c','h')
>>> M,N = 10,2
>>> q = get_neighbors(a.index('i'),N))
2d index: (0,8)
>>> q(a)
('j','t',10
>>> q = get_neighbors(a.index('i'),0)
>>> q(a)
('g','k')
>>>

Numpy 文档中有一个关于将 1d 事物作为 Nd 事物制作/处理的很好的讨论 - Internal memory layout of an ndarray

您描绘 1d --> 2d 转换的方式使用了列​​主要方案。我习惯于思考 row-major - 我编写了一个函数来接受/期望一个 (nrows,ncols) shape 参数,但在函数内部我有点切换到列主要处理。我不得不小心,所以也许这是一个糟糕的设计。