如何应用horzcat输出arrayfun

11次浏览(最近30天)
弗朗索瓦·法布尔
弗朗索瓦·法布尔 2020年4月30日
这是我问题的简化榜样:
A = [2 7 11;
5 9 11];这是我的起始数组
我想获得
B = [2 3 4 5 7 8 9 11];换句话说
现在,我的解决方案是
B = arrayfun(@(x,y))冒号(x,y), A(1,:), A(2,:),“UniformOutput”、假);
然后我使用[B{:}]作为逗号分隔的列表来索引另一个数组。
由于我是在一个for循环中执行这个操作的,其中a可能有数十万列,所以我希望通过水平连接arrayfun的输出参数来提高内存布局效率,从而避免创建单元格。
你知道这是否可能或者是否有更明智的方法吗?
提前谢谢!
2的评论
弗朗索瓦·法布尔
弗朗索瓦·法布尔 2020年4月30日
的确,这是一个很好的技巧。谢谢你!

登录评论。

接受的答案

Guillaume
Guillaume 2020年4月30日
我喜欢函数式编程 arrayfun (游戏邦注:它明确表示:将此函数应用于这些序列的所有元素)但请注意,如果速度非常关键,那么显式循环可能会更快。
arrayfun 你别无选择,只能通过中间单元阵列。在你的例子中,你不需要把它分成两行:
b = cell2mat(arrayfun(@(x,y)冒号(x,y),a(1,:),a(2,:),“UniformOutput”、假));%之所以有效,是因为arrayfun的单元格数组是行向量的行向量
使用显式循环,在你的例子中,你可以很容易地计算序列在最终数组中的位置,并完全避免单元格数组:
seqlengths = a(2,:) - a(1,:) + 1;
seqstarts = cumsum([1,seqlengths(1:end-1)]);
B =零(1,SEQSTARTS(END)-1);
colidx = 1:尺寸(a,2)
b(seqstarts(colidx)+(0:seqlengths(colidx)-1))= a(1,colidx):a(2,colidx);
结束
代码复杂度的增加是否值得我们去做。当然,上述方法可能不适用于您的实际用例。
1评论
弗朗索瓦·法布尔
弗朗索瓦·法布尔 2020年4月30日
我比较了A有20000列时的三种方法:
- arrayfun + [B{:}] - > 1.6s
- cell2mat(arrayfun()
-你的显式for循环- > 2.4-2.5s
但是,您的方法是正确的。我在这里找到了不同的方法 对冒号的概念进行矢量化 .在我的情况下,最快(0.8-0.9秒,20000列)的实现与你的略有不同:
seqlengths = a(2,:) - a(1,:) + 1;
查找每个块的结束和开始索引
partialLength = cumsum (seqlengths);
cumStart = [1 partallength (1:end-1)+1];
% preallocate输出
%然后循环开始/停止对,按顺序,并填充
numtot =总和(seqlengths);
B = 0(1、numtot);
colidx = 1:length(A(1,:)))
B(Cumstart(Colidx):PartialLength(Colidx))= A(1,Colidx):a(2,colidx);
结束
谢谢你的帮助!

登录评论。

更多的答案(0)

标签

下载188bet金宝搏


释放

R2020a

社区寻宝

在MATLAB中心找到宝藏,并发现社区如何可以帮助你!

开始狩猎!