How can I separate a sorted array into multiple at points referenced by another array?
1 回表示 (過去 30 日間)
古いコメントを表示
Say I have:
A = [1 4 7 9];
B = [0 2 3 5 6 8 10 11 12 13];
And I want to separate and organize the arrays as follows:
C{1} = [1 2 3];
C{2} = [4 5 6];
C{3} = [7 8];
C{4} = [9 10 11 12 13];
Any ideas how to efficiently do this?
I've done it with a for loop as such, but it's very slow as the real arrays are much larger:
for i = 1:length(A)-1
idx = A(i) > B & A(i+1)<= B;
C{i} = B(idx)';
end
C{:}
1 件のコメント
Matt J
2021 年 7 月 30 日
I have edited your post to run your code within it. The result doesn't agree with what you say it produces.
採用された回答
Matt J
2021 年 7 月 30 日
This might be what you want:
A = [1 4 7 9];
B = [1 2 3 4 5 6 7 8 9 10 11 12 13];
G=discretize(B,[A,inf]);
C=splitapply(@(x) {x}, B,G);
C{:}
0 件のコメント
その他の回答 (1 件)
Dave B
2021 年 7 月 30 日
編集済み: Dave B
2021 年 7 月 30 日
The discretize function (or the third output of thie histcounts function) is good for this kind of problem (it'll do the > and <= for you), you can avoid a loop with arrayfun although I'm not sure it'll really be faster nor easier to read.
I adjusted your data slightly to capture to capture the case where there's a value in B that's bigger than the largest A, and your solution slightly as it didn't produce any results as written.
A = [1 4 7 9 13];
B = [0 2 3 5 6 8 10 11 12 13 15];
% original solution
for i = 1:length(A)-1
idx = B > A(i) & B <= A(i+1);
C{i} = B(idx)';
end
% Alternate solution
%[~,~,ind]=histcounts(B,A); % this returns which 'bin'
ind = discretize(B,A);
C2 = arrayfun(@(x){B(ind==x)'}, 1:numel(A)-1);
isequal(C,C2)
% note that B(1) and B(end) are not in any bin, histcounts reports these as
% B(ind==0), while discretize reports these as B(isnan(ind))
Alternatives to arrayfun here include accumarray/splitapply. The syntax of accumarray is not for the faint of heart, I only mention it because often when doing an operation like this youre next step is to 'do something' with the contents of each group...like take the average etc. So if that's where you're headed next you might consider it. splitapply is a more modern and friendlier version, and (if you're really after a summary statistic) groupsummary may be even easier!
accumarray(ind(ind>0)',B(ind>0)',[],@(x) {x})'
splitapply(@(x) {x},B(ind>0)',ind(ind>0)')'
*edited to use discretize instead of histcounts, I always forget about this very useful function! Credit goes to @Matt J
0 件のコメント
参考
カテゴリ
Help Center および File Exchange で Loops and Conditional Statements についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!