首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Matlab索引逻辑索引

Matlab索引逻辑索引
EN

Stack Overflow用户
提问于 2013-01-30 14:54:20
回答 7查看 5.3K关注 0票数 10

我给出了一个指数列表,例如i = [3 5]和向量v = 1:6。我需要一个函数f,它返回给定索引i的向量v的逻辑映射,例如:

代码语言:javascript
复制
f(i, length(v)) = [0 0 1 0 1 0]

由于我将调用这个函数数百万次,我想使它尽可能快。是否有执行此任务的内置函数?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2013-01-30 15:35:25

我知道我在游戏中迟到了,但我真的很想找到一个和ismember一样优雅的更快的解决方案。事实上,有一种方法使用了无文档的ismembc函数:

代码语言:javascript
复制
ismembc(v, i)

基准测试

代码语言:javascript
复制
N = 7;
i = [3 5];

%// slayton's solution
tic
for ii = 1:1e5
    clear idx;
    idx(N) = false;
    idx(i) = true;
end
toc

%// H.Muster's solution
tic
for ii = 1:1e5
    v = 1:N;
    idx = ismember(v, i);
end
toc

%// Jonas' solution
tic
for ii = 1:1e5
    idx = sparse(i, 1, true, N, 1);
end
toc

%// ismembc solution
tic
for ii = 1:1e5
    v = 1:N;
    idx = ismembc(v, i);
end
toc

我得到的是:

代码语言:javascript
复制
Elapsed time is 1.482971 seconds.
Elapsed time is 6.369626 seconds.
Elapsed time is 2.039481 seconds.
Elapsed time is 0.776234 seconds.

令人惊讶的是,ismembc确实是最快的!

编辑:

对于非常大的N值(即当v是一个大数组时),更快的解决方案实际上是slayton的(以及HebeleHododo的)。你有相当多的策略可供选择,请仔细挑选:)

由H.Muster编辑:

以下是包括_ismemberoneoutput在内的基准测试结果

代码语言:javascript
复制
Slayton's solution:
   Elapsed time is 1.075650 seconds.
ismember:
   Elapsed time is 3.163412 seconds.
ismembc:
   Elapsed time is 0.390953 seconds.
_ismemberoneoutput:
   Elapsed time is 0.477098 seconds.

有趣的是,Jonas的解决方案不适合我,因为我得到了一个Index exceeds matrix dimensions.错误.

由胡加蒙编辑:

值得注意的是,ismembc需要两个输入都是数值输入、排序输入、非稀疏输入和非NaN值,这是来源文件中很容易忽略的细节。

票数 10
EN

Stack Overflow用户

发布于 2013-01-30 14:58:48

只需创建一个逻辑索引向量,并将所需位置设置为true/false

代码语言:javascript
复制
idx = false( size( v) );
idx( i ) = true;

这可以用如下所示的函数包装:

代码语言:javascript
复制
function idx = getLogicalIdx(size, i)
  idx = false(size);
  idx(i) = true;
end

如果您需要一个大小相同的索引向量,用于分配该向量一次的一百万次操作,然后在每次迭代时对其进行操作:

代码语言:javascript
复制
idx = false(size(v)); % allocate the vector
while( keepGoing)

  idx(i) = true; % set the desired values to true for this iteration

  doSomethingWithIndecies(idx);

  idx(i) = false; % set indices back to false for next iteration

end

如果您真的需要性能,那么您可以编写一个mex函数来完成这一任务。下面是我编写的一个非常基本的、未经测试的函数,比其他方法快约2倍:

代码语言:javascript
复制
#include <math.h>
#include <matrix.h>
#include <mex.h>

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    double M;
    double *in;

    M = mxGetScalar(prhs[0]);
    in = mxGetPr(prhs[1]);
    size_t N = mxGetNumberOfElements(prhs[1]);



    plhs[0] = mxCreateLogicalMatrix( M,1 );
    mxLogical *out= mxGetLogicals( plhs[0] );


    int i, ind;
    for (i=0; i<N; i++){
        out[ (int)in[i] ] = 1;
    }

}

在matlab中有几种不同的分配向量的方法。有些人比其他人更快,请参阅下面这篇无文档的Matlab文章,以获得一个很好的总结:

下面是比较不同方法的一些快速基准。最后一个方法是目前最快的,但它要求您对每个操作使用相同大小的逻辑索引向量。

代码语言:javascript
复制
N = 1000;
ITER = 1e5;

i = randi(5000,100,1);
sz = [N, 1];

fprintf('Create using false()\n');
tic;
for j = 1:ITER
    clear idx;
    idx = false( N, 1 );
    idx(i) = true;
end
toc;

fprintf('Create using indexing\n');
tic;
for j = 1:ITER
    clear idx;
    idx(N) = false;
    idx(i) = true;
end
toc;

fprintf('Create once, update as needed\n');
tic;
idx = false(N,1);
for j = 1:ITER
    idx(i) = true;
    idx(i) = false;
end
toc;

fprintf('Create using ismembc\n');
a = ones(N,1);
tic;
for j = 1:ITER

    idx = ismembc(1:N, i);
end
toc;
票数 5
EN

Stack Overflow用户

发布于 2013-01-30 15:08:20

您可以使用ismember

代码语言:javascript
复制
 i = [3 5];
 v = 1:6;

 ismember(v,i)

会回来

代码语言:javascript
复制
ans =

     0     0     1     0     1     0

对于可能更快的版本,您可以尝试

代码语言:javascript
复制
builtin('_ismemberoneoutput', v, i)

请注意,我只对您指定的行向量进行了测试。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14606863

复制
相关文章

相似问题

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