这是一个相对简单的一个。假设我有以下向量('V1'):
1
1
1
2
2
2
2
3
3
4
4
4
4
5
5
5
我想创建第二个向量V2,它从1开始,并在V1的每次迭代中增加,但随后重置为V1的新值。例如:
1
2
3
1
2
3
4
1
2
1
2
3
4
1
2
3
V1中可能只有一次迭代,或者多达6次。
解决方案可能会使用for循环,但我想有一个更简单的形式而不需要循环(想到'repmat')。
答案 0 :(得分:6)
没有循环的另一个建议。
首先计算重复值的数量
a=histc(v1,unique(v1));
构造计数数组
b = ones(1,sum(a));
现在将累计金额计算在适当的位置:
a = a(1:end-1);
b(cumsum(a)+1) = b(cumsum(a)+1) - a;
最后取累计金额
cumsum(b)
总计
v1 = [1,1,1,1,2,2,3,3,3,3,3,4];
a=histcounts(v1,[unique(v1),inf]);
b = ones(1,sum(a));
a = a(1:end-1);
b(cumsum(a)+1) = b(cumsum(a)+1) - a;
disp(cumsum(b))
<强> TIMEITs:强>
在随机排序的输入V1 = sort(randi(100,1e6,1));
上运行我在Matlab 2017a中获得以下时间。
参考代码:
function [] = SO()
V1 = sort(randi(100,1e6,1));
t1 = timeit(@() gnovice1(V1)); fprintf("* Gnovic's first suggestion: %d\n",t1);
t2 = timeit(@() gnovice2(V1)); fprintf("* Gnovic's second suggestion: %d\n",t2);
t3 = timeit(@() AVK(V1)); fprintf("* AVK's suggestion: %d\n",t3);
t4 = timeit(@() RadioJava(V1)); fprintf("* RadioJava's suggestion: %d\n",t4);
t5 = timeit(@() Nicky(V1)); fprintf("* Nicky's suggestion: %d\n",t5);
function []=gnovice1(V1)
V2 = accumarray(V1, 1, [], @(x) {1:numel(x)});
V2 = [V2{:}].';
function []=gnovice2(V1)
V2 = ones(size(V1));
V2([find(diff(V1))+1; end]) = 1-accumarray(V1, 1);
V2 = cumsum(V2(1:end-1));
function []=AVK(v)
a= v;
for i=unique(v)'
a(v==i)= 1:length(a(v==i));
end
function []=RadioJava(vec)
vec = vec(:).';
zero_separated=[1,vec(1:end-1)==vec(2:end)];
c=cumsum(zero_separated);
zeros_ind = ~zero_separated;
d = diff([1 c(zeros_ind)]);
zero_separated(zeros_ind) = -d;
output=cumsum(zero_separated);
function []=Nicky(v1)
v1 = v1(:).';
a=histcounts(v1,[unique(v1),inf]);
b = ones(1,sum(a));
a = a(1:end-1);
b(cumsum(a)+1) = b(cumsum(a)+1) - a;
b = cumsum(b);
答案 1 :(得分:5)
假设V1
已排序,这是使用accumarray
的矢量化解决方案:
V2 = accumarray(V1, 1, [], @(x) {1:numel(x)});
V2 = [V2{:}].';
答案 2 :(得分:5)
基于this answer中的第二种方法:
t = diff([0; find([diff(V1)~=0; true])]);
V2 = ones(sum(t), 1);
V2(cumsum(t(1:end-1))+1) = 1-t(1:end-1);
V2 = cumsum(V2);
答案 3 :(得分:3)
vec =[1 1 1 2 2 2 3 3 3];
zero_separated=[1,vec(1:end-1)==vec(2:end)]; % 0 at every new set
c=cumsum(zero_separated); % Temporary cumsum
zeros_ind = ~zero_separated;
d = diff([1 c(zeros_ind)]); % deltas in the temporary cumsum
zero_separated(zeros_ind) = -d; % Set zeros ind to delta
output=cumsum(zero_separated); % Calculate cumsum now
output = 1 2 3 1 2 3 1 2 3
基于this
答案 4 :(得分:2)
v = [1;1;1;2;2;2;2;3;3;4;4;4;4;5;5;5];
a= v;
for i=unique(v)'
a(v==i)= 1:length(a(v==i));
end
disp(a)