I would like to detect rows in a matrix which only occur once, also the column order does not matter. This relates to this discussion.
I have implemented several options (see below), and all work (note though I am a Julia novice so they might look silly), except they do not scale up well. They quickly become very slow. For instance
occursOnce4 below takes 75 seconds for a
(200406, 4) array on my machine:
I have also checked the
counter function as part of
DataStructures. That seems fast. However it produces counts on a unique set, which in this case is
Fs, i.e. the column direction sorted version of my input. So I cannot use the counts without the accompanying unique row set (unsorted). Also functions like
counter, and also
unique unfortunately do not export the indices for the unique members.
Any help would be appreciated. Thanks!
Here is an example mini matrix:
F=[1 2 3 4; 5 6 7 8; 4 3 2 1; 7 8 6 5; 1 2 5 6; 8 7 6 5; 5 6 7 8]
and more complex examples can be created using something like:
For background I am parsing 4 noded quadrilateral face arrays and am looking for faces that are not doubled, i.e. the boundary faces of a volumetric hexahedral mesh.
function occursOnce1(F) Fs=sort(F,dims=2) S=prod(string.(Fs),dims=2) L=zeros(Bool,size(F,1)) for q=1:1:size(F,1)#Loop over faces L[q]=count(S.==S[q])==1 end return L end function occursOnce2(F) Fs=sort(F,dims=2) L=zeros(Bool,size(F,1)) for q=1:1:size(F,1)#Loop over faces L[q]=count([Fs[q,:]==Fs[i,:] for i=1:1:size(F,1)])==1 end return L end function occursOnce3(F) Fs=sort(F,dims=2) #Sorted across columns L=zeros(Bool,size(F,1)) #Initialize boolean array for q=1:1:size(F,1) #Loop over faces L[q]=count(Fs[q,1].==Fs[:,1] .&& Fs[q,2].==Fs[:,2] .&& Fs[q,3].==Fs[:,3] .&& Fs[q,4].==Fs[:,4]) ==1 #Check count end return L end function occursOnce4(F) Fs=sort(F,dims=2) L=[count(==(r),eachrow(Fs)) for r in eachrow(Fs)].==1 return L end