矢量化- Matlab
Vectorization- Matlab
给定一个向量
X = [1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3]
我想生成一个这样的向量
Y = [1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5]
到目前为止我得到的是
idx = find(diff(X))
Y = [1:idx(1) 1:idx(2)-idx(1) 1:length(X)-idx(2)]
但我想知道是否有更优雅(稳健)的解决方案?
另一种方法是使用函数 unique
像这样:
[unqX ind Xout] = unique(X)
Y = [ind(1):ind(2) 1:ind(3)-ind(2) 1:length(X)-ind(3)]
这是否更优雅取决于您。
更稳健的方法是:
[unqX ind Xout] = unique(X)
for ii = 1:length(unqX)-1
Y(ind(ii):ind(ii+1)-1) = 1:(ind(ii+1)-ind(ii));
end
diff
、find
和 cumsum
的一种方法用于一般情况 -
%// Initialize array of 1s with the same size as input array and an
%// intention of using cumsum on it after placing "appropriate" values
%// at "strategic" places for getting the final output.
out = ones(size(X))
%// Find starting indices of each "group", except the first group, and
%// by group here we mean run of identical numbers.
idx = find(diff(X))+1
%// Place differentiated and subtracted values of indices at starting locations
out(idx) = 1-diff([1 idx])
%// Perform cumulative summation for the final output
Y = cumsum(out)
样本运行-
X =
1 1 1 1 2 2 3 3 3 3 3 4 4 5
Y =
1 2 3 4 1 2 1 2 3 4 5 1 2 1
只是为了好玩,但是习惯 bsxfun
基于替代解决方案-
%// Logical mask with each column of ones for presence of each group elements
mask = bsxfun(@eq,X(:),unique(X(:).')) %//'
%// Cumulative summation along columns and use masked values for final output
vals = cumsum(mask,1)
Y = vals(mask)
这是另一种方法:
Y = sum(triu(bsxfun(@eq, X, X.')), 1);
其工作方式如下:
- 将每个元素与所有其他元素进行比较 (
bsxfun(...)
)。
- 仅保留与当前或先前元素的比较 (
triu(...)
)。
- 统计,对于每个元素,进行了多少次比较
true
(sum(..., 1)
);也就是说,有多少元素,直到并包括当前元素,等于当前元素。
给定一个向量
X = [1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3]
我想生成一个这样的向量
Y = [1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5]
到目前为止我得到的是
idx = find(diff(X))
Y = [1:idx(1) 1:idx(2)-idx(1) 1:length(X)-idx(2)]
但我想知道是否有更优雅(稳健)的解决方案?
另一种方法是使用函数 unique
像这样:
[unqX ind Xout] = unique(X)
Y = [ind(1):ind(2) 1:ind(3)-ind(2) 1:length(X)-ind(3)]
这是否更优雅取决于您。
更稳健的方法是:
[unqX ind Xout] = unique(X)
for ii = 1:length(unqX)-1
Y(ind(ii):ind(ii+1)-1) = 1:(ind(ii+1)-ind(ii));
end
diff
、find
和 cumsum
的一种方法用于一般情况 -
%// Initialize array of 1s with the same size as input array and an
%// intention of using cumsum on it after placing "appropriate" values
%// at "strategic" places for getting the final output.
out = ones(size(X))
%// Find starting indices of each "group", except the first group, and
%// by group here we mean run of identical numbers.
idx = find(diff(X))+1
%// Place differentiated and subtracted values of indices at starting locations
out(idx) = 1-diff([1 idx])
%// Perform cumulative summation for the final output
Y = cumsum(out)
样本运行-
X =
1 1 1 1 2 2 3 3 3 3 3 4 4 5
Y =
1 2 3 4 1 2 1 2 3 4 5 1 2 1
只是为了好玩,但是习惯 bsxfun
基于替代解决方案-
%// Logical mask with each column of ones for presence of each group elements
mask = bsxfun(@eq,X(:),unique(X(:).')) %//'
%// Cumulative summation along columns and use masked values for final output
vals = cumsum(mask,1)
Y = vals(mask)
这是另一种方法:
Y = sum(triu(bsxfun(@eq, X, X.')), 1);
其工作方式如下:
- 将每个元素与所有其他元素进行比较 (
bsxfun(...)
)。 - 仅保留与当前或先前元素的比较 (
triu(...)
)。 - 统计,对于每个元素,进行了多少次比较
true
(sum(..., 1)
);也就是说,有多少元素,直到并包括当前元素,等于当前元素。