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

1 visualización (últimos 30 días)
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 comentario
Matt J
Matt J el 30 de Jul. de 2021
I have edited your post to run your code within it. The result doesn't agree with what you say it produces.

Iniciar sesión para comentar.

Respuesta aceptada

Matt J
Matt J el 30 de Jul. de 2021
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

Más respuestas (1)

Dave B
Dave B el 30 de Jul. de 2021
Editada: Dave B el 30 de Jul. de 2021
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

Categorías

Más información sobre Loops and Conditional Statements en Help Center y File Exchange.

Productos


Versión

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by