Remove overlapping index ranges within a single array
7 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
This is similar to a previous question: http://www.mathworks.com/matlabcentral/answers/68336-overlapping-time-intervals-without-for-while-loops
I have set of indices from a larger array in a row-wise manner:
totalMat = ones(15,1); a = [1,2; 3,5; 4,12; 6,11; 8,15];
These are meant to represent indices in a single column array (totalMat) that will be set to some value.
My goal is to determine from a top-down approach which which indices are not overlapping. Eg, the first set of indices (row), which is '1-2', does not overlap with anything, but the second set of indices ('3-5' overlaps with the next one, so the following index would be removed. Having removed the third row, the fourth does not overlap. The final row overlaps with the third, and is removed. The output would be:
b =
1 2
3 5
6 11
Then, ideally, I could set the indices in b to a value - i.e.
totalMat(1:2,3:5,6:11) = 20;
I've done this with while loops and subsequent eval() statements, but I need it to be vectorized to get it done in a reasonable amount of time - my totalMat can be as long as 32 million elements.
I'd like to do away with the eval() if possible. Lastly, this is not a homework question, but from a newbie programmer...
Thanks!
0 comentarios
Respuestas (3)
Azzi Abdelmalek
el 24 de Jul. de 2013
Editada: Azzi Abdelmalek
el 24 de Jul. de 2013
Edit
a = [1,2; 3,5; 3,6; 4,5; 8,10]
b=arrayfun(@(x) a(x,1):a(x,2),1:size(a,1),'un',0);
k=1;
while k<numel(b)
c=b(k+1:end);
idx=cellfun(@(x) any(ismember(x,b{k})),c);
if any(idx)
b(logical([ zeros(1,numel(b)-numel(idx)-1) 1 idx]))=[];
else
b(logical([ zeros(1,numel(b)-numel(idx)) idx]))=[];
end
k=k+1;
end
out=cell2mat(cellfun(@(x) [x(1) x(end)],b','un',0))
2 comentarios
Azzi Abdelmalek
el 24 de Jul. de 2013
a= [1,2;3,5;4,12;5,15;6,23;10,12;13,14;19,22;24,27;26,28];
b=arrayfun(@(x) a(x,1):a(x,2),1:size(a,1),'un',0);
k=1;
while k<numel(b)
c=b(k+1:end);
idx=cellfun(@(x) any(ismember(x,b{k})),c);
b(logical([ zeros(1,numel(b(1:k))) idx]))=[];
k=k+1;
end
out=cell2mat(cellfun(@(x) [x(1) x(end)],b','un',0))
4 comentarios
Jan
el 25 de Jul. de 2013
@Azzi: This can be simplified:
b(logical([ zeros(1,numel(b(1:k))), idx]))=[];
numel(b(1:k)) equals k. And converting ZEROS to LOGICAL is slower than using FALSE directly:
b([false(1, k), idx]) = [];
Jan
el 26 de Jul. de 2013
Editada: Jan
el 26 de Jul. de 2013
Some improvements of the loop you've posted as a comment:
totalMat2 = ones(numInd,1);
lenA = size(a, 1);
keeps = true(1, lenA); % as a vector instead of a matrix
currindex = 0;
exceed = a(:, 2) > length(totalMat2);
a(exceed, 2) = length(totalMat2);
for k = 1:lenA % length(a(:,1)) creates a(:,1) explicitly
if a(k,1) <= currindex
keeps(k) = false;
else
currindex = a(k, 2);
totalMat2(a(k,1):a(k,2)) = 20;
end
end
out2 = reshape(a(keeps, :), [], 2); % Automatic size matching
"i" should be avoided as variable to reduce confusions with the imaginary unit.
0 comentarios
Ver también
Categorías
Más información sobre Logical en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!