Unique (indices) method similar to MATLAB

Is there a method in Julia similar to MATLAB’s unique method? In Julia there is unique, but it does not have the same functionality. Specifically, I would like to get the list of indices of unique elements.

julia> unique([9,2,9,5])
3-element Array{Int64,1}:
 9
 2
 5

julia> indices = [1,2,4]
3-element Array{Int64,1}:
 1
 2
 4

In Matlab, the unique method provides the indices in the 2nd output argument, but Julia does not.

Is there any existing similar method? https://www.mathworks.com/help/matlab/ref/unique.html

x->findfirst.(.==(unique(x)), Ref(x) ) perhaps?

5 Likes

You can pass a function to unique in order to get the indices of the unique elements:

idx = unique(z -> x[z], 1:length(x))
x[idx]
7 Likes

This comment still seems relevant: https://groups.google.com/forum/#!topic/julia-users/205gVuPuZFU

One reason I probably still never notice is that we have Dict:

itr = pairs(a)
ua = Dict{valtype(itr),keytype(itr)}()
for (idx, val) in itr
    ua[val] = idx
end

julia> ua
Dict{Int64,Int64} with 3 entries:
  9 => 3
  2 => 2
  5 => 4

You can use Iterators.reverse if you prefer the first instance rather than last instance.

I’m well aware that looks longer than unique, but I nevertheless stand by the sense that I never miss it. I think it’s because in circumstances where I’d use it, the Dict may be useful in its own right. You also don’t have to read any documentation if you do it this way, whereas with Matlab’s unique you’re always poring over the docs to remember which index output is which.

2 Likes

In the link @tim.holy posted there is a link to a Github Issue:

2 Likes

For completeness, perhaps this thread should mention GroupSlices.jl (not written by me!) which in fact doesn’t return Matlab’s 3rd output:

A = [9, 2, 9, 5];
C = unique(A)
ia = unique(i -> A[i], 1:length(A)) # [1, 2, 4]
A[ia] == C
using GroupSlices
ig = groupslices(A) # [1, 2, 1, 4]
A[ig] == A # not matlab's ic
ia == firstinds(ig)
4 Likes