Matlab中如何高效将向量/元胞数组/结构体值按索引矩阵赋值?
高效索引映射实现方案
问题背景
假设我们有索引矩阵 A=[1,3;2,1],以及以下值集合:
B=[10,20,30]或B=[10;20;30]C={'aa';5;"g"}D是3x1或1x3结构体数组,包含字段values,D(ii).values为1x1数值数组,且vertcat(D.values)=[21;22;23]
需要生成与 A 尺寸相同的新数组/元胞数组/字符串数组,根据 A 中的索引位置填充对应值,预期结果:
b=foo(A,B)返回b=[10,30;20,10]c=bar(A,C)返回c={'aa',"g";5,'aa'}d=foobar(A,D.values)返回d=[21,23;22,21]
使用for循环处理2000x2000规模的数组时效率极低,需要更高效的实现方式。
高效实现方法
MATLAB中矢量化索引是这类问题的最优解,完全不需要循环,直接利用数组的索引映射特性即可,效率比循环高几个数量级:
1. 数值数组映射(对应B的情况)
不管B是行向量还是列向量,直接用A作为索引提取元素,再重塑为A的尺寸:
function b = foo(A, B) b = B(A); b = reshape(b, size(A)); end
测试示例:
A = [1,3;2,1]; B = [10,20,30]; foo(A,B) % 返回 [10,30;20,10] B_col = [10;20;30]; foo(A,B_col) % 同样返回 [10,30;20,10]
2. 元胞数组映射(对应C的情况)
元胞数组的索引规则和数值数组一致,直接用A作为索引提取:
function c = bar(A, C) c = C(A); c = reshape(c, size(A)); end
测试示例:
C = {'aa';5;"g"}; bar(A,C) % 返回 {'aa',"g";5,'aa'}
3. 结构体字段映射(对应D.values的情况)
D.values会返回逗号分隔的列表,先将其转换为数值数组,再用同样的索引方式:
function d = foobar(A, struct_values) val_array = [struct_values]; d = val_array(A); d = reshape(d, size(A)); end
测试示例:
D(1).values = 21; D(2).values = 22; D(3).values = 23; foobar(A,D.values) % 返回 [21,23;22,21]
原理说明
MATLAB的数组索引天生支持矩阵索引:当用一个矩阵作为索引提取另一个数组的元素时,会把索引矩阵的每个元素作为位置提取对应元素,返回列向量,最后用reshape恢复成原索引矩阵的尺寸即可。这种矢量化操作是底层优化的,处理2000x2000的矩阵几乎瞬间完成,远快于循环。
内容的提问来源于stack exchange,提问作者Crowley
相关产品推荐
相关产品推荐

