Remove overlapping index ranges within a single array
7 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
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 Kommentare
Antworten (3)
Azzi Abdelmalek
am 24 Jul. 2013
Bearbeitet: Azzi Abdelmalek
am 24 Jul. 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 Kommentare
Azzi Abdelmalek
am 24 Jul. 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 Kommentare
Jan
am 25 Jul. 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
am 26 Jul. 2013
Bearbeitet: Jan
am 26 Jul. 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 Kommentare
Siehe auch
Kategorien
Mehr zu Logical finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!