Matlab: поиск строк в матрице с фиксированным первым и последним элементом с векторизацией - PullRequest
1 голос
/ 18 января 2012

У меня есть матрица, подобная следующей (произвольные столбцы / строки):

1    0    0    0    0
1    2    0    0    0
1    2    3    0    0
1    2    3    4    0
1    2    3    4    5
1    2    5    0    0
1    2    5    3    0
1    2    5    3    4
1    4    0    0    0
1    4    2    0    0
1    4    2    3    0
1    4    2    5    0
1    4    2    5    3
1    4    5    0    0
1    4    5    3    0
2    0    0    0    0
2    3    0    0    0
2    3    4    0    0
2    3    4    5    0
2    5    0    0    0
2    5    3    0    0
2    5    3    4    0
3    0    0    0    0
3    4    0    0    0
3    4    2    0    0
3    4    2    5    0
3    4    5    0    0

, и теперь я хочу получить все строки, где первый элемент - это определенное значение X, а последний элемент (то естьпоследний элемент! = 0) - это определенное значение Y, ИЛИ повернулось: первым является Y, а последним - X.

Невозможно увидеть какой-либо быстрый код, который НЕ использует цикл for :(Спасибо!

EDIT : отфильтровать все строки с определенным первым элементом очень просто, вам не нужно мне здесь помогать, поэтому давайте предположим, что я хочу сделать только следующее:Отфильтруйте все строки, где последний элемент (т. Е. Последний элемент! = 0 в каждой строке) имеет значение X или Y.

EDIT Большое спасибо за ваши сообщения. Я сравнил три возможныхРешения с матрицей из 473408 * 10 элементов. Вот эталонный сценарий: http://pastebin.com/9hEAWw9a

Результаты были:

t1 = 2.9425 Jonas
t2 = 0.0999 Brendan
t3 = 0.0951 Oli

Так что, ребята, большое спасибо, я придерживаюсь решения Олии, таким образом, принять его. Спасибо за все другие решения!

Ответы [ 3 ]

5 голосов
/ 18 января 2012

Все, что вам нужно сделать, это найти линейные индексы последнего ненулевого элемента в каждой строке.Остальное легко:

[nRows,nCols] = size(A);
[u,v] = find(A); %# find all non-zero elements in A
%# for each row, find the highest column index with accumarray
%# and convert to linear index with sub2ind
lastIdx = sub2ind([nRows,nCols],(1:nRows)',accumarray(u,v,[nRows,1],@max,NaN));

Чтобы отфильтровать строки, вы можете написать

goodRows = A(:,1) == X & A(lastIdx) == Y
2 голосов
/ 18 января 2012

Вот хитрость: найдите числа с 0 справа и сложите их все:

H=[1 2 0 0 0;
   2 3 1 0 0;
   4 5 8 0 0;
   8 5 4 2 2];

lastNumber=sum(H.*[H(:,2:end)==0 true(size(H,1),1)],2)

ans =

     2
     1
     8
     2

Остальное легко:

firstNumber=H(:,1);

find( (firstNumber==f) & (lastNumber==l) )
1 голос
/ 18 января 2012

Это работает только в том случае, если числа в каждой строке представляют собой число ненулевых элементов, за которым следует серия нулей. то есть это не будет работать, если возможно следующее 1 0 3 4 0 0, я полагаю, что это невозможно на основании введенного вами образца ввода ...

% 'a' is your array
[nx, ny] = size(a);
inds = [0:ny:ny*(nx-1)]' + sum(a ~= 0, 2);
% Needs to transpose so that the indexing reads left-to-right
aT = a'; 
valid1 = aT(inds) == Y;
valid2 = a(:,1) == X;
valid = valid1 & valid2;
valid_rows = a(valid,:);

Это грязно, я знаю ...

...