我想为一个向量的每个元素应用一个线空间函数,并在最后创建一个完整的向量,是否有一些方便的方法呢?
具体来说,我想用矩阵 A 创建矩阵 B 而不使用使用循环,其中
A = [1; 2; 3; 4]
B = [1; 1; 2; 1; 2; 3; 1; 2; 3; 4]
如您所见,如果向量中的第三个元素是3
,那么"第三个向量"在输出向量中 B 将为[1:1:3]。我想要的步骤是固定的,对于任何元素都是精确的。
有人可以帮助我吗?
答案 0 :(得分:3)
由于B
的动态特性,没有任何循环就无法做到这一点。在这种情况下,我不会回避循环 - 特别是对于更新版本的MATLAB及其改进的JIT编译器。现在循环比矢量化操作更具竞争力,具体取决于你想要做什么。
最简单的方法是循环遍历A
和冒号运算符的所有值,并从1
转到A
中的每个值。
这样的事情会起作用:
A = [1; 2; 3; 4];
B = [];
for v = 1 : numel(A)
B = [B; (1:A(v)).'];
end
在每次迭代中,我们在A
中找到一个值,并创建一个从1到该值的向量。我们将所有这些连接成一个向量。请注意,不会执行错误检查,因此我们假设A
中的每个值都大于或等于1.
如果您热衷于单线,可以使用arrayfun
来创建一堆单元格数组并将它们挤压在一起,但性能明智这可能不是最佳解决方案:
A = [1; 2; 3; 4];
B = cell2mat(arrayfun(@(x) (1:x).', A, 'un', 0));
arrayfun
接受一个函数来对A
中的每个输入元素进行操作,因此该函数将创建一个从1到所需值的列向量。 un
是UniformOutput
的缩写,它设置为0意味着输出不均匀,因此我们要输出一堆单元格数组 - 每个矢量一个单元数组一个。创造了。最后,cell2mat
将所有单元阵列挤压在一起以创建单个列向量。它更优雅,但性能方面可能并非如此,因为有很多开销。
答案 1 :(得分:3)
以下两种避免循环的方法。
使用bsxfun
:这种方法是记忆 - (也许是时间)效率低下:
t = 1:max(A);
B = nonzeros(bsxfun(@times, t.', bsxfun(@le, t.', t)));
使用cumsum
:这样可以提高内存效率,但有点复杂:
A = nonzeros(A); % remove zeros, if any
B = ones(1, sum(A)); % initiallize
B(cumsum(A(1:end-1))+1) = 1-A(1:end-1); % write appropriate values...
B = cumsum(B).'; % ... so that the cumulative sum gives the desired output
循环可能是最好的方式:最简单,最清晰。
答案 2 :(得分:0)
您可以使用for循环执行此操作:
B = [];
for ii=1:size(A)
B = [B;(1:A(ii))'];
end
结果
B = [1; 1; 2; 1; 2; 3; 1; 2; 3; 4]