使用NumPy从邻居列表生成相邻三角形数组的技术问询
使用NumPy从邻居列表生成相邻三角形数组的技术问询
解决方案思路
你的核心需求是为每个点生成由[当前点, 邻居i, 邻居i+1]组成的三角形,其中最后一个三角形的邻居i+1要循环回到第一个邻居。当前代码的问题在于没有处理循环闭合,也没有把当前点加入到每个三角形中,而且zip_longest引入了不必要的None值。
下面是几个高效的实现方案:
方案一:利用NumPy的拼接和滑动窗口(向量化解法)
这种方法避免了显式循环,适合处理大规模数据:
import numpy as np from numpy.lib.stride_tricks import sliding_window_view # 原始输入数据 point_ids = np.array([0, 1, 2]) # 对应的点ID numnbrs = np.array([4,4,5]) nbrs = np.array([12, 2, 39, 40, 56, 2, 9, 10, 0, 1, 5, 21, 19]) # 1. 拆分邻居列表为每个点对应的邻居数组 split_indices = np.cumsum(numnbrs)[:-1] nbrs_per_point = np.split(nbrs, split_indices) # 2. 对每个点的邻居列表,拼接第一个邻居到末尾,实现循环闭合 closed_nbrs = [np.concatenate([nb, [nb[0]]]) for nb in nbrs_per_point] # 3. 生成滑动窗口,得到每个相邻邻居对 neighbor_pairs = [sliding_window_view(nb, 2) for nb in closed_nbrs] # 4. 为每个点重复自身ID,和邻居对组合成三角形 triangles = [] for pid, pairs in zip(point_ids, neighbor_pairs): # 生成重复当前点ID的数组,形状和pairs一致 pid_col = np.full((len(pairs), 1), pid) # 拼接成三角形数组 triangles.append(np.hstack([pid_col, pairs])) # 5. 合并所有三角形为最终数组 final_triangles = np.vstack(triangles)
运行后得到的final_triangles就是你想要的结果:
array([[ 0, 12, 2], [ 0, 2, 39], [ 0, 39, 40], [ 0, 40, 12], [ 1, 56, 2], [ 1, 2, 9], [ 1, 9, 10], [ 1, 10, 56], [ 2, 0, 1], [ 2, 1, 5], [ 2, 5, 21], [ 2, 21, 19], [ 2, 19, 0]])
方案二:简洁的列表推导式(适合小数据量)
如果你的数据量不大,用列表推导式会更直观,容易调试:
import numpy as np point_ids = [0, 1, 2] numnbrs = [4,4,5] nbrs = [12, 2, 39, 40, 56, 2, 9, 10, 0, 1, 5, 21, 19] # 拆分邻居列表 split_idx = np.cumsum(numnbrs)[:-1] nbrs_per_point = np.split(nbrs, split_idx) # 生成所有三角形 triangles = [] for pid, neighbors in zip(point_ids, nbrs_per_point): # 遍历每个邻居,和下一个邻居组合(最后一个邻居和第一个组合) for i in range(len(neighbors)): next_neighbor = neighbors[(i+1) % len(neighbors)] triangles.append([pid, neighbors[i], next_neighbor]) final_triangles = np.array(triangles)
为什么你的原始代码没成功?
itertools.zip_longest是为了对齐不同长度的数组,但这里我们不需要对齐,反而引入了None值;- 没有处理循环闭合的情况,最后一个邻居对应该是
[最后一个邻居, 第一个邻居]; - 没有把当前点的ID加入到每个三角形数组中,这是生成目标数组的关键部分。
备注:内容来源于stack exchange,提问作者ashwin
相关产品推荐
相关产品推荐

