Indexing with intercept for repeating values

1 view (last 30 days)
a = [1;1;1;2;3;3;4;5;6;7];
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7];
% I should get the following logical index as answer. Find position in b with equivalent in a.
idx = [1;1;1;0;0;1;1;1;0;0;1;1;1;0];
I tried intersect and ismember but cant seem to find an elegant way without looping. Thanks in advance!
  4 Comments
Matt J
Matt J on 8 Feb 2021
Couldn't this be a solution,
idx = [0;1;1;1;0;1;1;1;0;0;1;1;1;0];
hal9k
hal9k on 18 Feb 2021
Sorry no! The idx should have first 3 values set as 1,1,1 and 4th value is 0 (since there is no other 1's left in a).

Sign in to comment.

Accepted Answer

Matt J
Matt J on 8 Feb 2021
a = [1;1;1;2;3;3;4;5;6;7];
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7];
c = splitapply(@(x){(1:numel(x)).'<=sum(a==x(1))} , b , findgroups(b));
idx=cell2mat(c)
idx = 14x1 logical array
1 1 1 0 0 1 1 1 0 0
  5 Comments
hal9k
hal9k on 18 Feb 2021
Elegant solution but it took really long time for large arrays which I am working with.
Matt J
Matt J on 19 Feb 2021
Well, you didn't say it had to be fast. You just asked for a method that avoided loops.

Sign in to comment.

More Answers (2)

the cyclist
the cyclist on 8 Feb 2021
Here is one way:
a = [1;1;1;2;3;3;4;5;6;7];
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7];
idx = zeros(numel(b),1);
ii = 1;
while any(b) && any(a)
if a(1)==b(1)
idx(ii) = 1;
a(1) = [];
b(1) = [];
ii = ii+1;
elseif b(1) < a(1)
b(1) = [];
ii = ii+1;
else
a(1) = [];
end
end
idx
idx = 14×1
1 1 1 0 0 1 1 1 0 0
This method "cannibalizes" a and b, so you should make copies of those first if you need them.
  1 Comment
hal9k
hal9k on 22 Feb 2021
Edited: hal9k on 22 Feb 2021
This works but I wanted to avoid loops.

Sign in to comment.


the cyclist
the cyclist on 8 Feb 2021
Here is one way:
a = [1;1;1;2;3;3;4;5;6;7];
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7];
ha = histcounts(a,1:max(a)+1);
hb = histcounts(b,1:max(b)+1);
d = max(0,min(hb,ha));
idx = zeros(numel(b),1);
loc = cumsum([1,hb]);
for ii = 1:numel(d)
idx(loc(ii):loc(ii)+d(ii)-1) = 1;
end
idx
idx = 14×1
1 1 1 0 0 1 1 1 0 0
  2 Comments
hal9k
hal9k on 22 Feb 2021
I tested this but it would fail for this:
a = [1;1;1;2;3;3;4;5;6;7];
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7;8;8]; (a might not have all the elements(
Correct result is idx = [1;1;1;0;0;1;1;1;0;0;1;1;1;0;0;0];
But I got error with the code. So the above code would only work if a and b has same number of unique elements.
the cyclist
the cyclist on 22 Feb 2021
This had a very simple fix.
a = [1;1;1;2;3;3;4;5;6;7];
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7;8;8];
maxval = max([a;b]);
ha = histcounts(a,1:maxval+1);
hb = histcounts(b,1:maxval+1);
d = max(0,min(hb,ha));
idx = zeros(numel(b),1);
loc = cumsum([1,hb]);
for ii = 1:numel(d)
idx(loc(ii):loc(ii)+d(ii)-1) = 1;
end
idx
idx = 16×1
1 1 1 0 0 1 1 1 0 0

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!