Подход № 1
%// unique rows
unqrows = unique(X,'rows');
%// matches for each row against the unique rows and their cumsum values
matches_perunqrow = squeeze(all(bsxfun(@eq,X,permute(unqrows,[3 2 1])),2));
cumsum_unqrows = cumsum(matches_perunqrow,1);
%// Go through a row-order and get the cumsum values for the final output
[row,col] = find(matches_perunqrow);
[sorted_row,ind] = sort(row);
y=cumsum_unqrows(sub2ind(size(cumsum_unqrows),[1:size(cumsum_unqrows,1)]',col(ind)));
Пример запуска -
X =
1 2 0 1
1 0 1 2
1 2 3 4
2 4 6 8
1 2 0 1
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 0 1
out =
1
1
1
1
2
2
3
4
5
3
Подход № 2
%// unique rows
unqrows = unique(X,'rows');
%// matches for each row against the unique rows
matches_perunqrow = all(bsxfun(@eq,X,permute(unqrows,[3 2 1])),2)
%// Get the cumsum of matches and select only the matches for each row.
%// Since we need to go through a row-order, transpose the result
cumsum_perrow = squeeze(cumsum(matches_perunqrow,1).*matches_perunqrow)' %//'
%// Select the non zero values for the final output
y = cumsum_perrow(cumsum_perrow~=0)
Подход № 3
%// label each row based on their uniqueness
[~,~,v3] = unique(X,'rows')
matches_perunqrow = bsxfun(@eq,v3,1:size(X,1))
cumsum_unqrows = cumsum(matches_perunqrow,1);
%// Go through a row-order and get the cumsum values for the final output
[row,col] = find(matches_perunqrow);
[sorted_row,ind] = sort(row);
y=cumsum_unqrows(sub2ind(size(cumsum_unqrows),[1:size(cumsum_unqrows,1)]',col(ind)));
Подход # 4
%// label each row based on their uniqueness
[~,~,match_row_id] = unique(X,'rows');
%// matches for each row against the unique rows and their cumsum values
matches_perunqrow = bsxfun(@eq,match_row_id',[1:size(X,1)]');
cumsum_unqrows = cumsum(matches_perunqrow,2);
%// Select the cumsum values for the ouput based on the unique matches for each row
y = cumsum_unqrows(matches_perunqrow);
Это, кажется, быстро на самом деле в большинстве случаев. Я просто верю больше в векторизации, личный выбор, я думаю, так же потому, что я считаю, что графические процессоры имеют хороший шанс с векторизованными кодами. Итак, в качестве специального случая, когда я использовал 'X = randi (10,4000,2000);' и gpuArray для 'match_row_id' в моем решении, время выполнения фактически сравнимо с циклом цикла, и у меня есть достойный GPU для тестирования. +1 – Divakar
@Divakar Мне также нравится вызов векторизации кода.Вы пытались переписать часть '' bsxfun'' с явным циклом for, а затем применить остальные ваши подходы? Хотя '' bsxfun'' предлагает использовать хороший и короткий код, он может быть медленнее, чем петлевые версии. Что касается оптимизации скорости, это может быть проблемой. – Nras
Написание цикла для замены только части 'bsxfun' не приведет к улучшению. Я думаю, что в качестве кода цикла, ваш отлично. – Divakar