我有一个数值数组,其中一些具有重复项,例如:
a = [5;5;4;7;7;3;3;9;5;7]
我希望找出哪些是重复的,然后按顺序为每个重复项编号,同时将非重复项变为零。例如:
b = [1;1;0;2;2;3;3;0;1;2]
目前我采用的方法非常低效且不完整,使用了unique
函数和各种for
循环和if
语句,但我觉得应该有一个简单的答案。
什么是最有效的方法来获得这个答案?
以下是另一种方法:
a = [5;5;4;7;7;3;3;9;5;7];
[u, ~, w] = unique(a, 'stable');
s = find(sum(bsxfun(@eq, a, u.'), 1) > 1);
b = sum(bsxfun(@times, bsxfun(@eq, w, s), 1:numel(s)), 2);
a = [5;5;4;7;7;3;3;9;5;7];
[u, ~, w] = unique(a, 'stable');
s = find(sum(a==u.', 1) > 1);
b = sum((w==s).*(1:numel(s)), 2);
unique
、accumarray
和 ismember
来进行必要的调整:a = [5;5;4;7;7;3;3;9];
% Identify unique values and their counts
[uniquevals, ~, ia] = unique(a, 'stable'); % Stable keeps it in the same order
bincounts = accumarray(ia, 1); % Count the frequency of each index in ia
% Zero out singles
singles = uniquevals(bincounts <= 1);
[~, singleidx] = intersect(a, singles);
a(singleidx) = 0;
% Overwrite repeats
repeats = uniquevals(bincounts > 1);
[~, a] = ismember(a, repeats);
这将返回一个新的a
,其中包含:
a =
1 1 0 2 2 3 3 0
我们使用unique
来查找输入数组a
中的所有唯一值。我们还存储了可选的第三个输出,即将a
的值映射到其在唯一值数组中的索引。请注意,我们使用stable
选项以按a
中首次遇到的顺序获取唯一值;默认情况下,unique
的结果是排序的。
然后我们使用accumarray
累加从unique
得到的下标,这给我们每个索引的计数。使用逻辑索引,我们首先使用这些计数将单个实例归零。这些被归零后,我们可以使用ismember
的第二个输出来返回最终答案。
这里有一个基于索引、逻辑运算符和 cumsum 的解决方案:
x = [false; a(2:end)==a(1:end-1)]; %logical indexes of repeated elements except the first element of each block
y = [x(2:end)|x(1:end-1) ;x(end)]; %logical indexes of repeated elements
result = cumsum(~x&y).*y %cumsum(...):number all elements sequentially and (... .* y): making non-duplicates zero
编辑:
由于问题已经编辑,为了处理非连续的重复项,您可以这样做:
[s ii] = sort(a);
x = [false ;s(2:end)==s(1:end-1)];
y = [x(2:end)|x(1:end-1) ;x(end)];
first = ~x&y;
[~,ix]=sort(ii(first));
un(ix,1)=1:numel(ix);
result(ii,1)=un(cumsum(first)).*y;
a = [5;5;5;4;7;7;3;3;3;3;9];
。仍然非常整洁。 - Leander Moesinger[c, ia, ic] = unique(a, 'stable');
[~, b] = ismember(a, a(ia(accumarray(ic,1)>1)));
我使用了@excaza的答案中的一些想法,并进行了修改。
[5;5;4;7;7;3;3;9;5;5;4;7]
这样的输入是可能的吗?结果会是什么? - Luis Mendo