Efficient SORT function with random tie-breaking rule
4 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Hi, I'm trying to find if it already exists a function that do the exactly same thing of the built-in "sort" function except for the tie-breaking rule. Indeed, the sort function, in case of tie, maintains the initial order of the vector/matrix. On the contrary, I want to find a sort function that, in case of tie, choose at random the order of the entries. It already exists?? there exists some user function already written??
Just to inform you, i tried to write this:
function [sorted,idx]=randomSort2(m,dim,mode)
dim=2;
[sorted,idx]=sort(m,dim,mode);
diff=sorted(:,2:end)-sorted(:,1:end-1);
u=find(min(diff,[],2)==0);
for i=1:length(u)
k1=randperm(size(m,2));
[sorted(i,:),k2]=sort(m(i,k1),dim,mode);
idx(i,:)=k1(k2);
end
but obviously when there are a lot of ties it takes some seconds to perform. i want somethin more efficient, if it exists..
Thank you, Matteo
2 Commenti
Sean de Wolski
il 1 Mar 2012
So you want to randomly select the index in the case of duplicates, since the value will be the same?
Risposte (4)
Sean de Wolski
il 30 Mar 2012
For some reason this question came back to me when I was doing something completely unrelated the computer the other day. Will the values always be integers? If so, you could add a random value between -0.5 and 0.5 to the matrix, sort(), and then round(). Since the values are integers they will not switch positions with other integers, but will be random against equal integers:
m=[1 3 2;
2 1 2;
2 1 2];
[sorted,idx] = randomSort(m,2,'ascend')
Where randomSort() is this:
function [v idx] = randomSort(m,dim,direction)
[v,idx] = sort(m+(rand(size(m))-0.5),dim,direction);
v = round(v); %back to integers
This will handle matrices, dimensions changes etc.
1 Commento
Andrea Nardin
il 3 Dic 2020
Modificato: Andrea Nardin
il 3 Dic 2020
This is brilliant, it should be the top answer if integer numbers is the case. However it can be generalized to non-integers if you know (or compute each time) the minimum absolute difference among the set of numbers.
Of course if the min difference is infinitely small, then there is a finite precision problem in representing random numbers in such a small interval and so ties could not be differenciated much. But the solution could work for many cases.
Sean de Wolski
il 1 Mar 2012
One way:
x = [1 2 2 2 3 4 4 5];
[v,idx] = sort(x);
idxc = cumsum([1 logical(diff(v))]);
idx = cell2mat(accumarray(idxc',idx',[],@(x){x(randperm(numel(x)))}))
I'm sure there's a better way that doesn't use accumarray which requires building and destroying the cell array. Whatever this other method is would scale better to multiple dimensions as well.
0 Commenti
Vedere anche
Categorie
Scopri di più su Creating and Concatenating Matrices in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!