Сортировка матрицы с другой матрицей
Предположим, что у меня есть матрица A
, и я сортирую строки этой матрицы. Как копировать один и тот же порядок на матрице B
(одинаковый размер)?
например.
A = rand(3,4);
[val ind] = sort(A,2);
B = rand(3,4);
%// Reorder the elements of B according to the reordering of A
Это лучшее, что я придумал
m = size(A,1);
B = B(bsxfun(@plus,(ind-1)*m,(1:m)'));
Из любопытства любые альтернативы?
Обновление: отличное решение Jonas, профилированное на 2008a (XP):
n = n
0.048524 1.4632 1.4791 1.195 1.0662 1.108 1.0082 0.96335 0.93155 0.90532 0.88976
n = 2m
0.63202 1.3029 1.1112 1.0501 0.94703 0.92847 0.90411 0.8849 0.8667 0.92098 0.85569
Просто показывается, что циклы больше не являются анафемами для программистов MATLAB благодаря JITA (возможно).
Ответы
Ответ 1
Несколько более простой способ сделать это - использовать цикл
A = rand(3,4);
B = rand(3,4);
[sortedA,ind] = sort(A,2);
for r = 1:size(A,1)
B(r,:) = B(r,ind(r,:));
end
Интересно, что версия цикла быстрее для небольших (< 12 строк) и больших ( > ~ 700 строк) квадратных массивов (r2010a, OS X). Чем больше столбцов есть относительно строк, тем лучше работает цикл.
Вот код, который я быстро взломал для тестирования:
siz = 10:100:1010;
tt = zeros(100,2,length(siz));
for s = siz
for k = 1:100
A = rand(s,1*s);
B = rand(s,1*s);
[sortedA,ind] = sort(A,2);
tic;
for r = 1:size(A,1)
B(r,:) = B(r,ind(r,:));
end,tt(k,1,s==siz) = toc;
tic;
m = size(A,1);
B = B(bsxfun(@plus,(ind-1)*m,(1:m).'));
tt(k,2,s==siz) = toc;
end
end
m = squeeze(mean(tt,1));
m(1,:)./m(2,:)
Для квадратных массивов
ans =
0.7149 2.1508 1.2203 1.4684 1.2339 1.1855 1.0212 1.0201 0.8770 0.8584 0.8405
В два раза больше столбцов, чем строки (столько же строк)
ans =
0.8431 1.2874 1.3550 1.1311 0.9979 0.9921 0.8263 0.7697 0.6856 0.7004 0.7314
Ответ 2
Sort() возвращает индекс по размеру, который вы отсортировали. Вы можете явно создавать индексы для других измерений, которые заставляют строки оставаться стабильными, а затем использовать линейную индексацию для переупорядочения всего массива.
A = rand(3,4);
B = A; %// Start with same values so we can programmatically check result
[A2 ix2] = sort(A,2);
%// ix2 is the index along dimension 2, and we want dimension 1 to remain unchanged
ix1 = repmat([1:size(A,1)]', [1 size(A,2)]); %//'
%// Convert to linear index equivalent of the reordering of the sort() call
ix = sub2ind(size(A), ix1, ix2)
%// And apply it
B2 = B(ix)
ok = isequal(A2, B2) %// confirm reordering
Ответ 3
Разве вы не можете это сделать?
[val ind]=sort(A);
B=B(ind);
Это сработало для меня, если я не понимаю вашу проблему неправильно.