Remove overlapping index ranges within a single array
7 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
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 commentaires
Réponses (3)
Azzi Abdelmalek
le 24 Juil 2013
Modifié(e) : Azzi Abdelmalek
le 24 Juil 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 commentaires
Azzi Abdelmalek
le 24 Juil 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 commentaires
Jan
le 25 Juil 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
le 26 Juil 2013
Modifié(e) : Jan
le 26 Juil 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 commentaires
Voir également
Catégories
En savoir plus sur Logical dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!