[英]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的新舊版本之間)的排序可能不同。 因此,這是使用bsxfun的替代方法:
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.