Is there a built-in function that returns the permutations of a vector that are based on the unique elements of the vector, i.e. where the “structure” of the vector is retained ?
For example given y = ["a","a","a","b","b","c","c","c"]
, it would return ["a","a","a","b","b","c","c","c"]
, ["b","b","b","a","a","c","c","c"]
, ["a","a","a","c","c","b","b","b"]
, etc., but not for example ["a","a","b","a","b","c","c","c"]
.
I did implemented it in the following function, but I wonder if there is a better or built-in approach:
function getPermutations(v::AbstractArray{T,1};keepStructure=false) where {T}
if !keepStructure
return Combinatorics.permutations(v)
else
classes = unique(v)
nCl = length(classes)
N = size(v,1)
pSet = Combinatorics.permutations(1:nCl)
nP = length(pSet)
vPermutations = fill(similar(v),nP)
vOrigIdx = [findfirst(x -> x == v[i] , classes) for i in 1:N]
for (pIdx,perm) in enumerate(pSet)
vPermutations[pIdx] = classes[perm[vOrigIdx]] # permuted specific version
end
return vPermutations
end
end
julia> yp = collect(getPermutations(y))
40320-element Vector{Vector{String}}:
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "b", "c", "b", "c", "c"]
["a", "a", "a", "b", "c", "b", "c", "c"]
⋮
["c", "c", "c", "b", "a", "b", "a", "a"]
["c", "c", "c", "b", "b", "a", "a", "a"]
["c", "c", "c", "b", "b", "a", "a", "a"]
["c", "c", "c", "b", "b", "a", "a", "a"]
["c", "c", "c", "b", "b", "a", "a", "a"]
["c", "c", "c", "b", "b", "a", "a", "a"]
["c", "c", "c", "b", "b", "a", "a", "a"]
julia> yp = getPermutations(y,keepStructure=true)
6-element Vector{Vector{String}}:
["a", "a", "a", "b", "b", "c", "c", "c"]
["a", "a", "a", "c", "c", "b", "b", "b"]
["b", "b", "b", "a", "a", "c", "c", "c"]
["b", "b", "b", "c", "c", "a", "a", "a"]
["c", "c", "c", "a", "a", "b", "b", "b"]
["c", "c", "c", "b", "b", "a", "a", "a"]
(ps: the fact I do not collect on the whole permutation is intentional… it can become huge very quickly!)