簡體   English   中英

使用Matlab /八度音程進行數值分組,並且不重復在主數組中找到的值

[英]Numerical grouping using matlab / octave and not repeating values found in main array

我有大約100,000個數字,我希望將它們除以2或以2為增量進行分組。
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

你可以試試

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_all定義array_dyn_name -s。
使用eval是可怕的 ,相反,我們使用帶有動態字段名稱的結構

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預分配空間-這可能導致您的代碼運行比實際需要的要慢得多。 例如,參見有關預分配的線程

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM