在这篇文章中,我使用术语片来指n维数组B_i
的子数组A
,对于某些维d
,size(B_i, d)
是1。A
由size(A, d)
这样的切片组成,沿着维度d
连接起来。
例如,如果ndims(A)
为6,d
为3,则表单的表达式
A(:, :, i, :, :, :)
对于i
中的1:size(A, d)
,表示构成A
的所有切片(沿维度d
)。
像A(:, :, i, :, :, :)
这样的表达式的问题是,它不能象征性地推广到维数与6维不同的数组中的3维上的切片,例如,要在维2上得到A
的切片,就需要一个不同的表达式,A(:, i, :, :, :, :)
。这意味着这些表达式在不可知某些数组形状的代码中是无用的,因为这些数组将从中提取切片。
下面的函数是我的matlab-noob试图实现形状无关的切片.(名称slice
已经被采用,因此我将函数hslice
称为hyperslice
的缩写。)该函数的策略是将输入数组整形为一个合适的三维数组,沿着重塑后的数组的第二维取所需的切片,并将结果从原始的输入数组中整形成一个切片的形状。
function out = hslice(ndarray, d, i)
sz = size(ndarray);
pfx = sz(1:d-1); % dimensions before d
sfx = sz(d+1:end); % dimensions after d
tmp = reshape(ndarray, prod(pfx), sz(d), prod(sfx));
out = reshape(tmp(:, i, :), [pfx 1 sfx]);
end
是否有一种内置的,或至少更有效的方法来达到同样的结果(以一种不可知的方式)?
发布于 2014-03-20 08:36:32
嗯。您可以使用取消引用的单元格数组和“逗号分隔列表”之间的等价性,以及可以使用char ':‘作为索引来动态构造任意维度的A(:, :, :, i, :, ...)
调用这一事实。
function out = slice(A, ix, dim)
subses = repmat({':'}, [1 ndims(A)]);
subses{dim} = ix;
out = A(subses{:});
这将是完全概括的,并且将执行与原始静态A(:, :, i, :, ...)
表达式完全相同的“切片”索引操作,除了旋转这些字符串来设置它的开销之外。
或者,如果您愿意,只需使用sprintf
将该A(:, :, i, :, ...)
构造为字符串,然后在其上调用eval()
。但如果可能的话,我喜欢避免eval
。
请注意,您最初的实现使用的是快速操作,并且应该执行得很好,大约和这次一样快。我只是张贴这个,因为我认为它是非常可读的,回答你的问题,原来提出的,它可以应用于其他有用的东西。
片的分配
您还可以使用相同的单元内下标技术作为分配给数组片的lvalue。但是,您不能直接重用slice函数,因为它返回数组的提取子集,而不是lvalue引用。所以你可以做一个非常相似的函数来完成任务本身。
function A = slice_assign(A, ix, dim, B)
%SLICE_ASSIGN Assign new values to a "slice" of A
subses = repmat({':'}, [1 ndims(A)]);
subses{dim} = ix;
A(subses{:}) = B;
实际上,您还可能需要一个函数,该函数只返回单元格数组中的计算索引,因此您可以随身携带这些索引,并将它们反复用于赋值和引用。
function out = slice_subs(A, ix, dim)
subses = repmat({':'}, [1 ndims(A)]);
subses{dim} = ix;
out = subses;
发布于 2014-03-20 07:58:58
您可以尝试permute
和setdiff
将该维度移动到一致的位置:
function out = hslice(ndarray, d, i)
subdims = setdiff(1:ndims(ndarray),d);
sz = size(ndarray);
outsz = sz(subdims);
order = [d subdims];
ndarray = permute(ndarray,order);
out = reshape(ndarray(i,:),outsz);
end
例如:
d = 3; i = 2;
nd = randi(23,3,3,3,2);
out = hslice(nd,d,i); % out = squeeze(nd(:,:,i,:)) for d=3
但是,数据是在这里切片之前重写的,而不是用问题中的代码重写的。所以,我会和行动小组一起去!
https://stackoverflow.com/questions/22537326
复制相似问题