使用二维数组中的最大元素数找到一个非空交集

时间:2019-06-04 10:15:44

标签: ruby algorithm intersection

我有一个二维数组:

   keys = [[:reference],
     [:parent_ref, :kind],
     [:kind, :parent_ref, :reference],
     [:parent_ref, :kind, :status]]

假设我要所有这些数组的交集。我可以做的:

keys.reduce{|arr, acc| arr & acc}

,这将导致[],因为没有通用公共密钥。 现在,假设我要使用数组中元素的最大数量来找到“非空交集”。 例如,使用此“方法”的交集将为[:parent_ref,:kind],因为它是

的交集
[[:parent_ref, :kind],
         [:kind, :parent_ref, :reference],
         [:parent_ref, :kind, :status]]

我们只需要把[:reference]放在一边。

您将如何处理/创建这样的算法。

4 个答案:

答案 0 :(得分:0)

暴力,使用排列:

keys.combination(2).map { |a, b| a & b }.max_by(&:size)
#=> [:parent_ref, :kind]

查找使用的元素,也蛮力:

res = [:parent_ref, :kind]
keys.select { |e| e.sort & res.sort == res.sort }
#=> [[:parent_ref, :kind], [:kind, :parent_ref, :reference], [:parent_ref, :kind, :status]]

答案 1 :(得分:0)

假设二维数组是一个字符串数组,其中每个字符串都是一个字符数组。 假设我们有以下字符串:

CDB
BC
CBA
FDE
EDBC

首先按升序对每个字符串进行排序。

BCD
BC
ABC
DEF
BCDE

然后对字符串进行排序。

ABC
BC
BCD
BCDE
DEF

对于每个元素,找到出现在最长的连续字符串序列中的元素。在我们的示例中,它将是B和C。它们的连续字符串是具有非空交集的最大字符串。

答案 2 :(得分:0)

我相信您的问题与this one相关,而此answer是相关的。

您可以将输入内容翻译为简称以提高可读性:

matrix = [[:a], [:b, :c], [:c, :b, :a], [:b, :c, :d]]

您可以遍历值,并保留一个散列,其中包含每个值所在的所有集合:

matrix.each.with_index(1) do |row, i|
  row.each do |value|
    grouped_values[value] << i
  end
end

p grouped_values
# => {:a=>[1, 3], :b=>[2, 3, 4], :c=>[2, 3, 4], :d=>[4]}

因此:a存在于集合1和3中,b存在于集合2、3和4中...

然后您可以将这些集合分组在一起:

grouped_sets = Hash.new{|h, k| h[k] = []}

grouped_values.each do |value, sets|
  grouped_sets[sets] << value if sets.size > 1
end

p grouped_sets
# => {[1, 3]=>[:a], [2, 3, 4]=>[:b, :c]}

因此,集合1和3的交集为[:a],集合2、3和4的交集为[:b, :c]

最后,您可以选择具有最多集合或具有最多元素的交点。

答案 3 :(得分:0)

arr = [
  [:reference],
  [:parent_ref, :kind],
  [:kind, :parent_ref, :reference],
  [:parent_ref, :kind],
  [:parent_ref, :kind, :status],
  [:kind, :parent_ref, :kind]
]

请注意,我已修改示例中给出的keys,使其包括两种重复类型。

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]]]

这显示数组[:parent_ref, :kind]转换为集合后,是array的以下其他元素的子集:转换为集合后:

[[:parent_ref, :kind], [:kind, :parent_ref, :kind],
 [:kind, :parent_ref, :reference], [:parent_ref, :kind, :status]]

并且arr的其他任何元素(在arr的所有元素都转换为集合之后)没有更多的超集。

请注意,如果需要,可以将ga的计算链接起来。

请参见Set#<

如果arrarr的任何元素都不能包含重复项,则当然可以简化计算。

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]]]