Предположим, что у меня есть матрица 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):
0.048524 1.4632 1.4791 1.195 1.0662 1.108 1.0082 0.96335 0.93155 0.90532 0.88976
0.63202 1.3029 1.1112 1.0501 0.94703 0.92847 0.90411 0.8849 0.8667 0.92098 0.85569
Это просто идет, чтобы показать, что циклы не являются анафемой на программистов MATLAB больше благодаря JITA (возможно).
Несколько более ясный способ сделать это - использовать цикл
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
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