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

此生再无相见时 提交于 2019-12-23 02:31:24

问题


I have about 100,000 numbers that I would like to group together based on dividing by two or increments of two.
PS: The increment values may change and the values found in the main array "x" can only be used once.
I'm not sure how to check and stop the loop if a number in the "array_all" array has been repeated from the "x" array.

See example below

Example:

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

I'm trying to get the array_all array to look like this:

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]

and the dynamically named arrays to look like this

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: The reason I don't just stop at the array "array_dyn_name6" is due to that the numbers will not be that simple there will be thousands. And I won't know when they will repeat.

Sequence of events:
1. Start from the highest number in the x array and divide that number and it's output number by two and place that into another array called array_all, do this 3 times
2. Place each row of array_all into a dynamically named array called array_dyn_name
3. Do this for each value in the x array unless the number has already been used before in the array_all array

Note: As you can see the array_all array don't start with 4,3, or 2 because they were previously used in the array_all array

The code below works but I'm not sure how to check and stop the loop if a number in the "array_all" array has been repeated from the "x" array.

%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);

My output is below:

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: I'm using octave 3.8.1 it's like matlab


回答1:


You can try

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

Now, using ismember we prune the rows of array_all

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

By construction all elements of x are in array_all but we want to prune rows for which the first element already appears in previous rows.

firstRowToAppearIn = ceil(Locb/3); 

So

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

Now we can define array_dyn_name-s according to array_all.
Using eval is HORRIBLE, instead we use 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

It seems like ismember's second output (Locb) might be ordered differently between Matlab and octave (and maybe between newer and older versions of matlab). So, here's an alternative, using 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,
Apart from using eval, there is another cavity in your implementation: you do not pre-allocate space for array_all - this may cause your code to run significantly slower than it actually needs to be. See, for example this thread about pre-allocation.



来源:https://stackoverflow.com/questions/28263795/numerical-grouping-using-matlab-octave-and-not-repeating-values-found-in-main

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!