Is there an existing method that can get a value -> index map of a vector? For example, something that works like this:
function findalls(A::Vector)
d = Dict{eltype(A), Vector{Int}}()
for (i,v) in enumerate(A)
if !haskey(d, v)
d[v] = Vector{Int}()
end
push!(d[v], i)
end
d
end
EDIT:
My benchmark results are:
@bertschi 's approach is 2x faster than the second candidate at least on my use case (large vector, very few unique entries).
My own approach and @Dan 's one-line approach are the same, except that haskey is faster than get!, making my approach 1/3 faster. (if i use get! in my approach then they have the same performance)
FlexiGroups.groupfind is on par with @Dan 's approach while having more number of allocations and less overall size of allocations.
SplitApplyCombine.groupfind is 3.5x slower with 500x more allocations.
Honestly, what you’ve written in the start is great, @putianyi888 (just make the dict be a Dict{eltype(A), Vector{Int}}()). There’s nothing magical about built-in/existing functionality — the stuff you write can perform just as well.
The function is clearly inspired by SplitApplyCombine (:
For regular Vectors the difference is basically just performance, FlexiGroups are typically (always?) faster.
More generally, see a list of main differences at Alexander Plavin / FlexiGroups.jl · GitLab. Better support for different collection types, some helper features around grouping. I tried getting some of these into SplitApplyCombine, but didn’t manage to – so, created a more focused package.
Yeah I didn’t expect groupfind to actually be useful (:
I use group()/groupview()/groupmap() functions, but almost never really needed groupfind() myself. Added it simply because such a function already existed in SplitApplyCombine. Others (group()/…) have docstrings, maybe now it’s a sign that I should add one for groupfind as well.