How can I separate a sorted array into multiple at points referenced by another array?

조회 수: 1(최근 30일)
sma165
sma165 2021년 7월 30일
편집: Dave B 2021년 7월 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{:}
ans = 0×1 empty double column vector ans = 0×1 empty double column vector ans = 0×1 empty double column vector
ans = 1×5
9 10 11 12 13
  댓글 수: 1
Matt J
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
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{:}
ans = 1×3
1 2 3
ans = 1×3
4 5 6
ans = 1×2
7 8
ans = 1×5
9 10 11 12 13

추가 답변(1개)

Dave B
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

제품


릴리스

R2018a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by