Improve speed of appending array elements if not already in array
Since it is assumed that the data type is positive integer you can use logical matrix to store position of integers:
function f_logical( Ntest )
S = false;
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S(N) = true;
end
end
If the range of elements is large and the data has sparsity it may be beneficial to use sparse matrix:
function f_sparse( Ntest )
S = sparse(false);
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S(N) = true;
end
end
Comparing with the ismember
solution in Octave:
Elapsed time for <ismember> is 1.54181 seconds.
Elapsed time for <sparse> is 0.266474 seconds.
Elapsed time for <logical> is 0.0189412 seconds.
I guess you can use the following code to speed up
X = setdiff(N,S);
S(end + (1:length(X))) = X;
- Remarks
X = N(~ismember(N,S))
andX = setdiff(N,S)
are both fine to find the elements that inN
but not inS
, but the key step for speeding up the appending process is the following way
S(end + (1:length(X))) = X;
- Performance Comparison
rng(0);
Ntest = randi([1,1e4],1e4,1e4);
f = @()f_union( Ntest );
fprintf( 'union: \t%.3f sec\n', timeit( f ) );
f = @()f_ismember_v1( Ntest );
fprintf( 'ismember_v1: \t%.3f sec\n', timeit( f ) );
f = @()f_ismember_v2( Ntest );
fprintf( 'ismember_v2: \t%.3f sec\n', timeit( f ) );
f = @()f_setdiff_v1( Ntest );
fprintf( 'setdiff_v1: \t%.3f sec\n', timeit( f ) );
f = @()f_setdiff_v2( Ntest );
fprintf( 'setdiff_v2: \t%.3f sec\n', timeit( f ) );
function f_union( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = union(S,N,'stable');
end
end
function f_ismember_v1( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S; N(~ismember(N,S))];
end
end
function f_ismember_v2( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
X = N(~ismember(N,S));
S(end + (1:length(X))) = X;
end
end
function f_setdiff_v1( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
S = [S;setdiff(N,S)];
end
end
function f_setdiff_v2( Ntest )
S = [];
for ii = 1:size(Ntest,2)
N = Ntest(:,ii);
X = setdiff(N,S);
S(end + (1:length(X))) = X;
end
end
giving
union: 13.314 sec
ismember_v1: 5.836 sec
ismember_v2: 5.658 sec
setdiff_v1: 4.371 sec
setdiff_v2: 4.248 sec