使用matlab / octave进行数字分组,而不是重复在主数组中找到的值

时间:2015-02-01 14:30:33

标签: arrays matlab octave numerical-methods

我有大约100,000个号码,我想根据两个或两个增量组合在一起。
PS:增量值可能会改变,主阵列“x”中的值只能使用一次。
如果从“x”数组重复“array_all”数组中的数字,我不确定如何检查和停止循环。

见下面的例子

示例:

x=[9,8,7,6,5,4,3,2,1]

我正在尝试将array_all数组看起来像这样:

array_all= 
[  9.00000   4.50000   2.25000
   8.00000   4.00000   2.00000
   7.00000   3.50000   1.75000
   6.00000   3.00000   1.50000
   5.00000   2.50000   1.25000
   1.00000   0.50000   0.25000]

,动态命名的数组看起来像这样

array_dyn_name1=[9,4.5,2.25]
array_dyn_name2=[8,4,2]
array_dyn_name3=[7,3.5,1.75]
array_dyn_name4=[6,3,1.5]
array_dyn_name5=[5,2.5,1.25]
array_dyn_name6=[1,.5,.25]

PS:我不仅仅停留在数组“array_dyn_name6”的原因是因为数字不会那么简单就会有数千个。我不知道他们什么时候会重复。

事件顺序:
1.从 x 数组中的最高数字开始,将该数字和输出数除以2并将其放入另一个名为 array_all 的数组中,执行此操作3次
2.将 array_all 的每一行放入名为 array_dyn_name 的动态命名数组中 3.对 x 数组中的每个值执行此操作,除非之前已在 array_all 数组中使用过该数字

注意:您可以看到 array_all数组不是以4,3或2开头,因为它们以前在 array_all数组中使用

下面的代码有效,但是我不知道如果从“x”数组中重复“array_all”数组中的数字,如何检查和停止循环。

%test grouping
clear all, clc, tic, clf; 

x=[9,8,7,6,5,4,3,2,1]
div=[1,2,4] %numbers to use as divisor
array_all=[];
for ii=1:length(x)

    for jj=1:length(div)
        array_all(ii,jj)=x(ii)/div(jj) %divide each number and successive number by div 
    end

    genvarname('array_dyn_name',  num2str(ii)) %create dynamic variable
    eval(['array_dyn_name' num2str(ii) '= array_all(ii,:)']) %places row into dynamic variable 

end
fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

我的输出如下:

array_all =

   9.00000   4.50000   2.25000
   8.00000   4.00000   2.00000
   7.00000   3.50000   1.75000
   6.00000   3.00000   1.50000
   5.00000   2.50000   1.25000
   4.00000   2.00000   1.00000
   3.00000   1.50000   0.75000
   2.00000   1.00000   0.50000
   1.00000   0.50000   0.25000

PS:我使用八度音阶3.8.1就像matlab

1 个答案:

答案 0 :(得分:2)

你可以尝试

array_all = bsxfun( @times, x(:), [1 .5 .25] ); %// generate for all values

现在,使用ismember我们修剪array_all

[Lia Locb] = ismember( x(:), reshape( array_all.', [], 1 ) ); %// order elements of array_all row by row

通过构造,x的所有元素都在array_all中,但我们想要修剪第一个元素已经出现在前一行中的行。

firstRowToAppearIn = ceil(Locb/3); 

所以

toBePruned = 1:numel(x) > firstRowToAppearIn; %// prune elements that appear in array_all in a row preceding their location in x

array_all(toBePruned,:) = []; %// remove those lines

现在我们可以根据array_dyn_name定义array_all - Using eval is HORRIBLE,而是使用structure with dynamic field names

st = struct();
for ii=1:size(array_all,1)
    nm = sprintf('array_dyn_name%d',ii);
    st.(nm) = array_all(ii,:);
end

似乎ismember的第二个输出(Locb)可能在Matlab和octave之间以不同方式排序(可能在新版和旧版本的matlab之间)。所以,这是另一种选择,使用

eq_ = bsxfun( @eq, array_all, permute( x(:), [3 2 1] ) );
eq_ = max( eq_, [], 2 ); %// we do not care at which column of array_all x appeared
[mx firstRowToAppearIn] = max( squeeze(eq_), [], 1 ); 

PS,
除了使用eval之外,您的实现中还有另一个空洞:您没有为array_all预先分配空间 - 这可能会导致您的代码运行速度明显慢于实际需要的速度。有关预分配的信息,请参阅this thread