Как удалить измерение массива, где элементы суммируются до нуля? - PullRequest
2 голосов
/ 03 апреля 2010

Я назначаю трехмерный массив, который содержит некоторую информацию для ряда различных вариантов загрузки. Каждая строка в массиве определяет конкретный загрузочный регистр (из которых 3), и я хотел бы удалить загрузочный регистр (то есть строку), если ВСЕ элементы строки (в 3D) равны нулю.

Код, который у меня есть на данный момент:

Array = zeros(3,5) %# Initialise array
Numloadcases = 3;

Array(:,:,1) = [10 10 10 10 10;
                0   0  0  0  0;
                0   0  0  0  0;]; %# Expand to a 3D array 

Array(:,:,2) = [10 10 10 10 10;
                0  0  0  0  0;
                0  0  0  0  0;];

Array(:,:,3) = [10 10 10 10 10;
                0  0  0  0  0;
                0  0  20  0  0;];

Array(:,:,4) = [10 10 10 10 10;
                0  0  0  0  0;
                0  0  20  0  0;];

%# And to remove the second row:

for i = 1:Numloadcases
  if sum(Array(i,:,:)) == 0
    Array(i,:,:) = [];
  end
end

В данный момент цикл for, который я должен удалить, вызывает ошибку индексации, так как размер массива изменяется в цикле.

Кто-нибудь может найти способ обойти это?

Ответы [ 2 ]

3 голосов
/ 04 апреля 2010

Вот альтернатива зацикливанию, использующая функции ALL и логическое индексирование :

isAllZero = all(all(Array == 0,3),2);  %# Logical index of rows with all zeroes
Array = Array(~isAllZero,:,:);  %# Keep rows that have non-zero values
%# Or...
Array(isAllZero,:,:) = [];      %# Set rows with all zeroes to the empty matrix
0 голосов
/ 04 апреля 2010

команда matlab "any" сообщает вам, есть ли ненулевые элементы.

sum (Array (i,:, :) == 0) выдаст true для некоторых смесей положительных и отрицательных элементов (например, [1 1 -2]), что, вероятно, не способ сделать это.

Я бы хотел быть умным и рассказать вам, как это сделать без циклов for, но накладные расходы на цикл for здесь невелики, и код, вероятно, будет более понятным, если вы продолжите цикл for. Ваша ошибка в этой строке: Array(i,:,:) = [] что, вероятно, заставляет Matlab кричать на вас о несоответствии количества элементов

исправление состоит в том, чтобы отслеживать, какие элементы вы хотите удалить, а затем позаботиться об этом в конце цикла

valid = false([1 Numloadcases]); %preallocate
for i = 1:Numloadcases
   valid(i) = any(any(Array(i,:,:)));
end
Array = Array(valid,:,:);

Если Array - это обычный массив ND, вы, вероятно, не захотите собирать кучу команд, поэтому эта альтернативная формулировка будет работать

valid = false([1 Numloacases]);
for i = 1:Numloadcases
   valid(i) = any(reshape(Array(i,:,:), 1, []);
end
Array = Array(valid,:,:);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...