如何在使用原始索引

时间:2016-04-29 07:38:51

标签: matlab matrix multidimensional-array indexing

我希望您的建议能让我的代码更快(更优雅)。特别是,sub2ind(和if-loop)根据matlab分析器显着减慢了速度。我将尝试尽可能简单地从代码中解释我的需求。

假设我有以下问题,为简单起见。

每个城市的每个公民都有一辆特定品牌和特定颜色的汽车。 我想要的是一个4D多维数组Data_4D(City,Citizen,Car_brand,Car_color),我只能使用这四个维度作为索引来操作(读取和修改)。

然后,我想将我的多维数组重塑为一维数组Data_1D with

length(Data_1D)=(City*Citizen*Car_brand*Car_color)

元素的顺序必须遵循索引规则: 假设City=2, Citizen=2, Car_brand=2, Car_color=2;

的示例
    Data_1D(1)=Data_4D(1,1,1,1)
    Data_1D(2)=Data_4D(1,1,1,2)
    Data_1D(3)=Data_4D(1,1,2,1)
    Data_1D(4)=Data_4D(1,1,2,2)
    Data_1D(5)=Data_4D(1,2,1,1)
    Data_1D(6)=Data_4D(1,2,1,2)
    Data_1D(7)=Data_4D(1,2,2,1)
    Data_1D(8)=Data_4D(1,2,2,2)
    Data_1D(9)=Data_4D(2,1,1,1)
    Data_1D(10)=Data_4D(2,1,1,2)
    Data_1D(11)=Data_4D(2,1,2,1)
    Data_1D(12)=Data_4D(2,1,2,2)
    Data_1D(13)=Data_4D(2,2,1,1)
    Data_1D(14)=Data_4D(2,2,1,2)
    Data_1D(15)=Data_4D(2,2,2,1)
    Data_1D(16)=Data_4D(2,2,2,2)

之后我会得到这个1D数组,形状如上,我需要创建一个矩阵Matrix_Final( NRows,length(Data_1D)),其中每一行都是一个数组Data_1D。在每行NRows中,数组Data_1D将具有相同数量的元素但具有不同的值 行数还取决于四个维度City,Citizen,Car_brand,Car_color中的一些(或全部)(遵循与Data_1D相同的索引规则),并且每行中构建的数组也必须根据值的大小进行操作。矩阵行(通过使用四个索引,这是NRows和Data_1D的通用规则)。

实施例: 假设City=2, Citizen=2, Car_brand=2, Car_color=2; 假设 NRows取决于所有四个维度。 我会Matrix_Final( length(DATA_1D), length(DATA_1D))。 我希望我的数组DATA_1D的所有数据都是零,除了一个元素,它必须是与(City,Citizen,Car_brand,Car_color)具有相同索引值NRows(City,Citizen,Car_brand,Car_color)的元素。 因此,在NRows(1)行,只有Data_1D(1)非零。对于此示例,结果是眼睛矩阵。

clc
  clear all
  %Dimensions Definition
  City=2;
  Citizen=2;
  Car_brand=2;
  Car_color=2;
  %Length of Data
  Length_Data_1D=City*Citizen*Car_brand*Car_color;
  %preallocation Matrix_Final
  Matrix_Final=zeros(City*Citizen*Car_brand*Car_color, Length_Data_1D);
  %indexes of the dimensions
  indexes_array_carcolor=repmat(repelem([1:Car_color], 1), [1 City*Citizen*Car_brand]);
  indexes_array_carbrand=repmat(repelem([1:Car_brand], Car_color), [1 City*Citizen]);
  indexes_array_citizen=repmat(repelem([1:Citizen],Car_brand*Car_color),[1 City]);
  indexes_array_city=repmat(repelem([1:City],Citizen*Car_brand*Car_color),[1 1]);
  %Initializing loop variable
  column_Matrix_final=1;

  for CITY_selected=1:City
     for CITIZEN_selected=1:Citizen 
         for CAR_BRAND_selected=1:Car_brand
           for CAR_COLOR_selected=1:Car_color
            %Data_4D Construction
            Data_4D=zeros(City,Citizen,Car_brand,Car_color);
              for city=1:length(indexes_array_city)
                for citizen=1:length(indexes_array_citizen)
                    for car_brand=1:length(indexes_array_carbrand)
                        for car_color=1:length(indexes_array_carcolor)
                            if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
                                  && indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
                                  indexes_array_carcolor(car_color)==CAR_COLOR_selected)
                          Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
                              indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1; 
                            end
                      end
                  end
              end
       end
      %Data_4D transformation into array Data_1D
      Data_1D=zeros(1,City*Citizen*Car_brand*Car_color);
      tic=1;
      for city=1:City
          for citizen=1:Citizen
              for car_brand=1:Car_brand
                  for car_color=1:Car_color
                      Data_1D(tic)=Data_4D(city,citizen,car_brand,car_color);
                      tic=tic+1;
                  end
              end
          end
      end
      %Adding Data_1D to the next for of Matrix_Final
      Matrix_Final(column_Matrix_final,:)=Data_1D;
      column_Matrix_final=column_Matrix_final+1;
      %Display of the four most external loops indexes to show code
      %advancement
       CAR_COLOR_selected
     end
         CAR_BRAND_selected
  end
      CITIZEN_selected
 end
         CITY_selected 
end
      spy(Matrix_Final)

如果你添加例如

  && indexes_array_carcolor(car_color)==2 
在if循环中

,只有Data_1D(City,Citizen,Car_brand,Car_color=2)NRows(City,Citizen,Car_brand,Car_color=2)的元素将为非零。

我想知道是否有更快的方法来设置问题,但保持使用四个索引(City,Citizen,Car_brand,Car_color)操作Data_1D和Matrix_Final的相同能力以及关联NRows和Data_1D的元素使用这四个索引。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

这就是你编码的方式

if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
     && indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
   indexes_array_carcolor(car_color)==CAR_COLOR_selected)
   Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
   indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1; 
end

另一种方式1

if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
     && indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
    indexes_array_carcolor(car_color)==CAR_COLOR_selected)
    Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
    indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=1; 
end

另一种方式2

Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
     indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=double((indexes_array_city(city)==CITY_selected)& ...
                                  (indexes_array_citizen(citizen)==CITIZEN_selected)& ...
                                  (indexes_array_carbrand(car_brand)==CAR_BRAND_selected)& ...
                                  (indexes_array_carcolor(car_color)==CAR_COLOR_selected));

所有这三个都会产生相同的结果。尝试哪个更快并使用它。

%% Data_4D transformation into array Data_1D
Data_4D_size=size(Data_4D);
Data_1D_size=prod(Data_4D_size);
temp = permute(Data_4D, [4 3 2 1]);
Data_1D=reshape(temp,Data_1D_size,1);

将此用于4D到1D转换

  

如果还需要更快的速度。将其编译为mex。编译的代码运行得更快。