arr = [
[:reference],
[:parent_ref, :kind],
[:kind, :parent_ref, :reference],
[:parent_ref, :kind],
[:parent_ref, :kind, :status],
[:kind, :parent_ref, :kind]
]
Note that I've modified keys
given in the example to include two types of duplicates.
require 'set'
h = arr.each_with_object(Hash.new { |h,k| h[k] = [] }) { |a,h| h[a.to_set] << a }
#=> {#<Set: {:reference}>=>[[:reference]],
# #<Set: {:parent_ref, :kind}>=>[[:parent_ref, :kind],
# [:parent_ref, :kind], [:kind, :parent_ref, :kind]],
# #<Set: {:kind, :parent_ref, :reference}>=>[[:kind, :parent_ref, :reference]],
# #<Set: {:parent_ref, :kind, :status}>=>[[:parent_ref, :kind, :status]]}
g = h.each_key.with_object({}) do |k,g|
g[k] = h[k].dup
h.each { |kk,v| g[k].concat(v) if k < kk }
end
#=> {#<Set: {:reference}>=>[[:reference], [:kind, :parent_ref, :reference]],
# #<Set: {:parent_ref, :kind}>=>[[:parent_ref, :kind], [:parent_ref, :kind],
# [:kind, :parent_ref, :kind], [:kind, :parent_ref, :reference],
# [:parent_ref, :kind, :status]],
# #<Set: {:kind, :parent_ref, :reference}>=>[[:kind, :parent_ref, :reference]],
# #<Set: {:parent_ref, :kind, :status}>=>[[:parent_ref, :kind, :status]]}
a = g.max_by { |k,v| v.size }
#=> [#<Set: {:parent_ref, :kind}>, [[:parent_ref, :kind], [:parent_ref, :kind],
# [:kind, :parent_ref, :kind], [:kind, :parent_ref, :reference],
# [:parent_ref, :kind, :status]]]
[a.last.first, a.last.drop(1)]
#=> [[:parent_ref, :kind], [[:parent_ref, :kind], [:kind, :parent_ref, :kind],
# [:kind, :parent_ref, :reference], [:parent_ref, :kind, :status]]]
This shows the array [:parent_ref, :kind]
, when converted to a set, is a subset of the following other elements of array
after being converted to sets:
[[:parent_ref, :kind], [:kind, :parent_ref, :kind],
[:kind, :parent_ref, :reference], [:parent_ref, :kind, :status]]
and that no other element of arr
(after all elements of arr
are converted to sets) has a greater number of supersets.
Note that, if desired, the calculations of g
and a
can be chained.
See Set#<.
If neither arr
nor any element of arr
may contain duplicates, the calculations are of course simplified.
arr = [
[:reference],
[:parent_ref, :kind],
[:kind, :parent_ref, :reference],
[:parent_ref, :kind, :status]
]
require 'set'
sets = arr.map(&:to_set)
#=> [#<Set: {:reference}>, #<Set: {:parent_ref, :kind}>,
# #<Set: {:kind, :parent_ref, :reference}>, #<Set: {:parent_ref, :kind, :status}>]
h = sets.each_with_object(Hash.new { |h,k| h[k] = [] }) { |s,h|
sets.each { |ss| h[s] << ss if s < ss } }
#=> {#<Set: {:reference}>=>[#<Set: {:kind, :parent_ref, :reference}>],
# #<Set: {:parent_ref, :kind}>=>[#<Set: {:kind, :parent_ref, :reference}>,
# #<Set: {:parent_ref, :kind, :status}>]}
k, v = h.max_by { |_,v| v.size }
#=> [#<Set: {:parent_ref, :kind}>,
# [#<Set: {:kind, :parent_ref, :reference}>, #<Set: {:parent_ref, :kind, :status}>]]
[k.to_a, v.map(&:to_a)]
#=> [[:parent_ref, :kind],
# [[:kind, :parent_ref, :reference], [:parent_ref, :kind, :status]]]