Maximum number of repeated values over an array
5 views (last 30 days)
Show older comments
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.
Thanks in advance,
Alessandro
0 Comments
Accepted Answer
Stephen23
on 20 Jan 2021
Edited: Stephen23
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{:}).'
2 Comments
Stephen23
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{:})
More Answers (1)
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);
0 Comments
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!