【问题标题】:Find a non empty intersection using the maximum number of elements in a bidimensional array使用二维数组中的最大元素数查找非空交集
【发布时间】:2019-06-04 10:15:44
【问题描述】:

我有一个二维数组:

   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]放在一边。

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

【问题讨论】:

  • 不确定我是否理解问题和您的示例。 “使用最大数量的元素”是什么意思?你能用不同的方式解释吗?
  • 对我来说,在这种情况下,元素似乎是内部数组。所以他正在寻找涉及数组数量最多的交集。请参见本例中的红色:i.imgur.com/bxLBqf3.png

标签: ruby algorithm intersection


【解决方案1】:

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

CDB
BC
CBA
FDE
EDBC

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

BCD
BC
ABC
DEF
BCDE

然后对字符串进行排序。

ABC
BC
BCD
BCDE
DEF

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

【讨论】:

    【解决方案2】:

    蛮力,使用排列:

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

    【讨论】:

      【解决方案3】:

      我相信您的问题与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]

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

      【讨论】:

      • 我认为您在这里缺少一些交叉点:假设您有b=&gt;[2,3,4]c=&gt;[2,3,4,5] 这个解决方案将错过[2,3,4] =&gt; [:b, :c]
      • @DavidGeismar:看来你是对的。它找到与最多子集的交集,而不是与最多元素的交集。
      【解决方案4】:
      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]]] 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-12
        • 1970-01-01
        • 1970-01-01
        • 2017-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-24
        相关资源
        最近更新 更多