首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Matlab:将大于1 (-1)的元素转换为1 (-1)的序列。

Matlab:将大于1 (-1)的元素转换为1 (-1)的序列。
EN

Stack Overflow用户
提问于 2012-10-27 03:42:27
回答 2查看 770关注 0票数 4

更新:我做了一些测试,对于不同大小的输入向量,Jonas的解决方案是最快的。特别是,正如angainor所指出的那样,解决方案的规模大得令人难以置信地好--这是一个重要的测试,因为通常是大尺寸的问题促使我们提出这样的问题。感谢乔纳斯和特姆珠切对你的解决方案-基于解决大尺寸问题的效率,我给答案勾选乔纳斯。

我的问题:,我有这个列向量:

代码语言:javascript
复制
Vec = [0; 1; 2; -1; -3; 0; 0; 2; 1; -1];

我想把每一个大于一个的元素转换成一个长度等于元素值的序列。类似地,我想把每个小于负1的元素转换成一个负数序列。因此,输出向量应该如下所示:

代码语言:javascript
复制
VecLong = [0; 1; 1; 1; -1; -1; -1; -1; 0; 0; 1; 1; 1; -1];

请注意,每个2已更改为2个1,而-3已更改为3-1。

代码语言:javascript
复制
VecTemp = Vec;
VecTemp(VecTemp == 0) = 1;
VecLong = NaN(sum(abs(VecTemp)), 1);
c = 1;
for n = 1:length(Vec)
    if abs(Vec(n)) <= 1
        VecLong(c) = Vec(n);
        c = c + 1;
    else
        VecLong(c:c + abs(Vec(n))) = sign(Vec(n));
        c = c + abs(Vec(n));
    end    
end

这感觉不太优雅。有人能提出更好的方法吗?注意:您可以假设Vec只包含整数值。谢谢您的所有建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-27 07:24:09

您可以使用好的老累加方法来正确地重复这些条目。请注意,如果您想将所有内容都放在一行中,那么我将分配一些临时变量,您可以去掉这些变量。

代码语言:javascript
复制
%# create a list of values to repeat
signVec = sign(Vec);

%# create a list of corresponding indices that repeat
%# as often as the value in signVec has to be repeated

tmp = max(abs(Vec),1); %# max: zeros have to be repeated once
index = zeros(sum(tmp),1);
index([1;cumsum(tmp(1:end-1))+1])=1; %# assign ones a pivots for cumsum
index = cumsum(index); %# create repeating indices

%# repeat
out = signVec(index);
out'
out =

     0     1     1     1    -1    -1    -1    -1     0     0     1     1     1    -1
票数 3
EN

Stack Overflow用户

发布于 2012-10-27 04:18:47

编辑:我想到了另一种(稍显晦涩的),但更短的方法来做到这一点,而且它比你拥有的循环更快。

代码语言:javascript
复制
for rep=1:100000
    #% original loop-based solution
end
toc
Elapsed time is 2.768822 seconds.

#% bsxfun-based indexing alternative
tic;
for rep=1:100000
TempVec=abs(Vec);TempVec(Vec==0)=1;
LongVec = sign(Vec(sum(bsxfun(@gt,1:sum(TempVec),cumsum(TempVec)))+1))
end
toc
Elapsed time is 1.798339 seconds.

与原来的答案相比,这个答案也是很好的,至少在某种程度上是这样的。有个表演的好地方。

代码语言:javascript
复制
Vec = repmat(OrigVec,10,1);
#% test with 100,000 loops
#% loop-based solution:
Elapsed time is 19.005226 seconds.
#% bsxfun-based solution:
Elapsed time is 4.411316 seconds.

Vec = repmat(OrigVer,1000,1);
#% test with 1,000 loops - 100,000 would be horribly slow
#% loop-based solution:
Elapsed time is 18.105728 seconds.
#% bsxfun-based solution:
Elapsed time is 98.699396 seconds.

bsxfun是将向量展开成一个矩阵,然后用和将其折叠。对于非常大的向量,与循环相比,这是不必要的内存,因此它最终会丢失。不过,在此之前,它做得相当好。

原始的,缓慢的回答:

这里有一条单线:

代码语言:javascript
复制
out=cell2mat(arrayfun(@(x) repmat(((x>0)*2)-1+(x==0),max(1,abs(x)),1),Vec,'uni',0));
out' =

     0   1   1   1  -1  -1  -1  -1   0   0   1   1   1  -1

怎么回事:

代码语言:javascript
复制
((x>0)*2)-1 + (x==0) #% if an integer is >0, make it a 1, <0 becomes -1, 0 stays 0 

max(1,abs(x)) #% figure out how many times to replicate the value  

arrayfun(@(x) (the above stuff), Vec, 'uni', 0) #% apply the function  
 #% to each element in the array, generating a cell array output

cell2mat( (the above stuff) ) #% convert back to a matrix 
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13097042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档