Maximum number of repeated values over an array

9 views (last 30 days)
Alessandro Togni on 20 Jan 2021
Commented: Stephen Cobeldick on 20 Jan 2021
Hi,
i'm working with an array of thousands of elements and i've to limit the repeated values to 10.
Let say:
a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9];
has to become:
[0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,9].
Any suggestion would be appreciated.
Alessandro

Stephen Cobeldick on 20 Jan 2021
Edited: Stephen Cobeldick on 20 Jan 2021
a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9];
x = cumsum([true;diff(a(:))~=0]);
f = @(v){v(1:min(end,10))};
c = accumarray(x,a(:),[],f);
b = vertcat(c{:}).'
b = 1×28
0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 9
Stephen Cobeldick on 20 Jan 2021
a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9];
d = find([true;diff(a(:));true]);
f = @(b,e)(b+10):(e-1);
c = arrayfun(f,d(1:end-1),d(2:end),'uni',0);
x = horzcat(c{:})
x = 1×21
11 12 13 14 15 16 17 18 19 20 21 22 40 41 42 43 44 45 46 47 48

Jan on 20 Jan 2021
Edited: Jan on 20 Jan 2021
a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, ...
5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9];
[v, n] = RunLength(a);
b = RunLength(v, min(n, 10));
If you do not have a C compiler installed, use the function RunLength_M of this submission.
Alternatively:
function out = LimitRunLength(in, nMax)
x = in(:);
d = [true; diff(x) ~= 0]; % TRUE if values change
b = x(d); % Elements without repetitions
k = find([d', true]); % Indices of changes
n = diff(k); % Number of repetitions
n = min(n, nMax); % Limit the run lengths
d = cumsum(n); % Cummulated run lengths
index = zeros(1, d(end)); % Pre-allocate
index(d(1:end-1)+1) = 1; % Get the indices where the value changes
index(1) = 1; % First element is treated as "changed" also
out = b(cumsum(index)); % Cummulated indices
% Let the output be a row vector, if the input is a row:
if size(in, 2) > 1
out = out.';
end
end
[EDITED] You ask for the indices of the removed elements:
a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,5, ...
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9];
nMax = 10;
[v, n, idx] = RunLength_M(a);
b = RunLength_M(v, min(n, nMax));
crop = find(n > nMax);
idx = [idx, numel(a) + 1];
q = zeros(1, numel(a));
q(idx(crop) + nMax) = 1;
q(idx(crop + 1)) = -1;
removed = find(cumsum(q));
And as next alternative a straight forward loop:
del = false(size(a));
cur = NaN;
for k = 1:numel(a)
if a(k) == cur
len = len + 1;
del(k) = (len > nMax);
else
cur = a(k);
len = 1;
end
end
b = a(~del);
removed = find(del);