Anthony
Anthony

Reputation: 83

Removing elements from an array

Problem:

I have two arrays A and B:

A = [0, 1, 2, 3]; %A will always be from 0 to N where N in this case is 3.

B = [0, 1, 3,   1, 9, 4, 6,    2, 5, 9, 10, 11,   3, 8, 1, 5, 9, 10]; 

weights_B = [3, 4, 5, 6]; 

I want to compare the first element of A to the first 3 elements of B and the second element of A to the next 4 elements of B. If the elements of A are equal I remove it from B. So in example:

 if (A(1) == B(1:3))
 remove A(1) from B 

Similarly,

I want to compare A(2) to the next 4 elements of B i.e. to B(4:7):

if (A(2) == B(4:7))
remove A(2) from B 

I want to compare A(3) to the next 5 elements of B i.e. to B(8:12)

if (A(3) == B(8:12))
remove A(3) from B 

I want to compare A(4) to the next 6 elements of B i.e. to B(13:18)

if (A(4) == B(13:18))
remove A(4) from B 

Note: The array weights_B determines the number of elements in B that should be respectively compared to A(1), A(2), .. , A(4)

So in the end B should have the following elements:

  B = [1, 3, 9, 4, 6, 5, 9, 10, 11, 8, 1, 5, 9, 10]; 

Needed Solution:

Is there any way I can do this without having to hard-code the indices?

Upvotes: 1

Views: 123

Answers (5)

Anton
Anton

Reputation: 4684

Try this

A = [0, 1, 2, 3]; 
B = [0, 1, 3,   1, 9, 4, 6,    2, 5, 9, 10, 11,   3, 8, 1, 5, 9, 10]; 

weights_B = A + A(end);

border_0 = zeros(size(A));
border_1 = zeros(size(A));

border_0(1) = 1;
border_1(end) = length(B);

for i= 2:length(A)
    border_0(i) = border_0(i-1) + weights_B(i-1);
    border_1(i-1) = border_0(i)-1;
end

C = [];
for i= 1:length(border_0)
    shift = 0;
    if (i > 1)
        shift = border_1(i-1);
    end

    C = [C  B(    find(B(border_0(i):border_1(i))~=A(i)) + shift     )]
end

Upvotes: 2

Dev-iL
Dev-iL

Reputation: 24179

For the sake of diversity, here's a way to do this using splitapply:

function out = q50982235
A = 0:3;
B = [0, 1, 3,   1, 9, 4, 6,    2, 5, 9, 10, 11,   3, 8, 1, 5, 9, 10]; 
weights_B = [3, 4, 5, 6];

a_ind = 0; % acts as a "global" variable for the inner function

G = repelem( 1:numel(weights_B), weights_B ); % this creates a vector of groups
out = cell2mat( splitapply(@movdif, B, G) );

function out = movdif(B)
  a_ind = a_ind + 1;
  out = {B(B ~= A(a_ind))};
end

end

The above works because the order of processed groups is predictable.

This solution requires R2015b.

Upvotes: 4

Luis Mendo
Luis Mendo

Reputation: 112769

Here's a way without hard-coding:

Bw = mat2cell(B, 1, weights_B); % split into chunks
result = cell(size(Bw)); % initiallize result
for k = 1: numel(A)
    result{k} = Bw{k}(Bw{k}~=A(k)); % fill each chunk of the result
end
result = [result{:}]; % concatenate into a row vector

Upvotes: 4

Ahmad Bin Shafaat
Ahmad Bin Shafaat

Reputation: 125

Since you want to compare the elements of A with first 3 and then 4 elements of B respectively, you would need to involve indexes. You could simply use loop for it.

for(int i=0;i<B.length;i++){
 if((A[0]==B[i])&&i<3){
 B[i]=B[i+1];
 }
 else if((A[0]==B[i])&&i>3){}
  B[i]=B[i+1];
 }

Then adjust the updated size of array B.

Upvotes: -4

Siva Srinivas Kolukula
Siva Srinivas Kolukula

Reputation: 1241

   A = [0, 1]; 
   B = [0, 1, 3, 1, 4, 5, 6]; 
   % Split B into cells 
   C{1} = B(1:3) ;    % this can be coded if more splits are required 
   C{2} = B(4:end) ;
   % removing the lements 
   for i = 1:2
       C{i}(C{i}==A(i))=[] ;  % remove the elements in C{i} present in A(i)
   end
   cell2mat(C)

Upvotes: -2

Related Questions