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 commentaires

madhan ravi
madhan ravi le 8 Fév 2021
Are a and b always sorted?
hal9k
hal9k le 8 Fév 2021
Modifié(e) : hal9k le 8 Fév 2021
yes. In ascending order.
Couldn't this be a solution,
idx = [0;1;1;1;0;1;1;1;0;0;1;1;1;0];
hal9k
hal9k le 18 Fév 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).

Connectez-vous pour commenter.

 Réponse acceptée

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 commentaires

Could it be
c = splitapply(@(x){(1:numel(x)).'<=sum(a==x(1))} , b , b); %? since b is already sorted?
No, for example,
a = [1;1;1;2;3;3;4;5;6;7]+1;
b = [1;1;1;1;1;2;3;4;4;4;5;6;7;7]+1;
c = splitapply(@(x){(1:numel(x)).'<=sum(a==x(1))} , b , b);
Error using splitapply (line 111)
For N groups, every integer between 1 and N must occur at least once in the vector of group numbers.
madhan ravi
madhan ravi le 8 Fév 2021
Thanks Matt for the clarification.
hal9k
hal9k le 18 Fév 2021
Elegant solution but it took really long time for large arrays which I am working with.
Matt J
Matt J le 19 Fév 2021
Well, you didn't say it had to be fast. You just asked for a method that avoided loops.

Connectez-vous pour commenter.

Plus de réponses (2)

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 commentaire

hal9k
hal9k le 22 Fév 2021
Modifié(e) : hal9k le 22 Fév 2021
This works but I wanted to avoid loops.

Connectez-vous pour commenter.

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 commentaires

hal9k
hal9k le 22 Fév 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.
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

Connectez-vous pour commenter.

Catégories

En savoir plus sur Characters and Strings dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by