Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 匹配具有最大相似性的2个哈希的有效方法_Ruby On Rails_Ruby_Algorithm_Hashmap_Ruby Hash - Fatal编程技术网

Ruby on rails 匹配具有最大相似性的2个哈希的有效方法

Ruby on rails 匹配具有最大相似性的2个哈希的有效方法,ruby-on-rails,ruby,algorithm,hashmap,ruby-hash,Ruby On Rails,Ruby,Algorithm,Hashmap,Ruby Hash,有没有一种有效的方法可以找到两个id 类似选项\u ID的最大数量 上述例子的答案是 [[1148612624],[1458814590] 我已经尝试过的是- 获取每个散列并将其opt_id与数组中其他剩余散列的opt_id进行比较 当前哈希的opt_id与这2个id中最匹配的哈希 因此,我在每个散列上循环的次数与数组中散列的次数相同-O(n^2) 您可以检查数组中的差异。所以,如果它返回空数组,或者说元素数较少,则表示它们相等或几乎相等 例如: [ {"id"=>

有没有一种有效的方法可以找到两个id 类似选项\u ID的最大数量

上述例子的答案是

[[1148612624],[1458814590]

我已经尝试过的是-

  • 获取每个散列并将其
    opt_id
    与数组中其他剩余散列的
    opt_id
    进行比较
  • 当前哈希的opt_id与这2个id中最匹配的哈希
  • 因此,我在每个散列上循环的次数与数组中散列的次数相同-
    O(n^2)

  • 您可以检查数组中的差异。所以,如果它返回空数组,或者说元素数较少,则表示它们相等或几乎相等

    例如:

    [
      {"id"=>11486, "opt_ids"=> [3545, 3546, 3548, 3550] },
      {"id"=>12624, "opt_ids"=> [3545, 3396, 3548, 3550] }, 
      {"id"=>14588, "opt_ids"=> [3394, 3396, 3397, 3399] }, 
      {"id"=>14589, "opt_ids"=> [3394, 3545, 3398, 3548] }, 
      {"id"=>14590, "opt_ids"=> [3394, 3396, 3397, 3399, 3545, 3547, 3548, 3551, 3653, 3655, 3657, 3660, 3772, 3775, 3777, 3778]},
      .....
      .....
      ...
      ...
    
    ]
    

    假设我们得到一个非负整数
    max_diff
    ,这样两个整数,
    n1
    n2
    被视为“相似”,如果

    并具体说明:

    arr = [
      { "id"=>11486, "opt_ids"=> [3545, 3546, 3548, 3550] },
      { "id"=>12624, "opt_ids"=> [3545, 3396, 3548, 3550] }, 
      { "id"=>14588, "opt_ids"=> [3394, 3396, 3397, 3399] }, 
      { "id"=>14589, "opt_ids"=> [3394, 3545, 3398, 3548] }, 
      { "id"=>14590, "opt_ids"=> [3394, 3396, 3397, 3399] },
      { "id"=>14591, "opt_ids"=> [3545, 3547, 3548, 3551] },
      { "id"=>14592, "opt_ids"=> [3653, 3655, 3657, 3660] },
      { "id"=>14593, "opt_ids"=> [3772, 3775, 3777, 3778] }
    ]
    
    我将假设我们将根据元素对的计数对这些散列(以及与
    “id”
    相关的值对)进行排序
    [h1[“opt_id”][I],h2[“opt_id”][j]]
    ,它们在我上面的定义中是“相似的”。这可能与您的想法不一致,但它可能是一个有用的起点。我简要介绍了
    max_diff
    始终为零的情况


    考虑哈希值
    arr[0]
    arr[3]
    “opt_id”
    值:

    max_diff = 3
    
    如下表所示,
    a0
    中的
    3545
    类似于
    a3
    的两个元素,
    3545
    3548
    。类似地,
    a0
    中的
    3546
    3548
    3550
    分别类似于
    2
    2
    1
    元素
    a3
    ,这意味着散列
    arr[0]
    arr[3]
    可以被认为具有
    7
    的相似性分数

    a0 = arr[0]["opt_ids"]
      #=> [3545, 3546, 3548, 3550]
    a3 = arr[3]["opt_ids"]
      #=> [3394, 3545, 3398, 3548]
    

    我们可以使用以下帮助器方法实现此计数

      a0      a3      #
    ____________________
    3545: 3545, 3548 (2)
    3546: 3545, 3548 (2)
    3548: 3545, 3548 (2)
    3550: 3548       (1)
    

    如果我误解了这个问题,并且
    max_diff
    始终为零,并且如果所有数组
    arr[I][“opt_id”]
    都包含唯一的元素(就像问题中的示例中那样),则可以编写

    count_similar(a0, a3, max_diff)
      #=> 7
    
    并删除
    max_diff
    参数


    我们现在可以按如下方式计算成对ID的相似性度量:

    def count_similar(a1, a2)
      (a1 & a2).size
    end
    
    然后,我们可以计算这样的度量,以确定五对具有最高相似性分数的组合:

    similarities(arr, max_diff)
      #=> {[11486, 12624]=> 9, [11486, 14588]=>0, [11486, 14589]=> 7, [11486, 14590]=>0,
      #    [11486, 14591]=>13, [11486, 14592]=>0, [11486, 14593]=> 0, [12624, 14588]=>4,
      #    [12624, 14589]=> 7, [12624, 14590]=>4, [12624, 14591]=>10, [12624, 14592]=>0,
      #    [12624, 14593]=> 0, [14588, 14589]=>6, [14588, 14590]=>14, [14588, 14591]=>0,
      #    [14588, 14592]=> 0, [14588, 14593]=>0, [14589, 14590]=> 6, [14589, 14591]=>7,
      #    [14589, 14592]=> 0, [14589, 14593]=>0, [14590, 14591]=> 0, [14590, 14592]=>0,
      #    [14590, 14593]=> 0, [14591, 14592]=>0, [14591, 14593]=> 0, [14592, 14593]=>0}
    
    这表明这对ID,
    14588
    14590
    (来自
    arr[2]
    arr[4]
    )的相似性得分最高,为
    14

    我把表格放在这里,上面有相同的数据。我从许多不同的表中创建了一个视图

    用SQL来做,这就是它擅长的

    使用自联接获取每对的重叠数

    similarities(arr, max_diff).max_by(5, &:last)
      #=> [[[14588, 14590], 14], [[11486, 14591], 13], [[12624, 14591], 10],
      #    [[11486, 12624],  9], [[12624, 14589],  7]]
    

    即使没有索引,它的性能也应该比把它全部放到Ruby中要好得多。

    对于上面的例子,答案是什么?你试过什么?“循环”很模糊。@Schwern谢谢你的提问,我已经更新了我的问题。请让我知道现在是否更清楚?是的,谢谢。您有多少数据?数据多久更改一次?你想要什么样的表演?将其放入SQLite可能是有意义的。@Schwern此数据已经是数据库的一部分,我已经从那里聚合了它。目前,数组中的哈希数可以在50到500之间变化。我想要的性能是,为了根据最大相似选项id匹配2个id,我不必循环遍历每个哈希。选项ID的数量每周都会增加。在SQL中这样做可能更容易、更快。你能给我看一下原始的表格吗?没错,但我还是得把a和b、c、d一一比较一下。尽量避免这种情况。不过数组的长度不同。所以一个空的差异并不意味着什么:
    a-b#=>[]
    可能仅仅意味着
    a
    是空的。设置交叉点(
    &
    )可能是一个更好的主意。谢谢你的回答,让我分析一下,然后返回。谢谢你的回答,让我分析一下,然后返回。谢谢你在这个方向上指导我,尽管有点不同。它帮助我有了另一个视角@cary
    with overlaps as (
      select
        a.emp_id emp_id1,
        b.emp_id emp_id2,
        count(a.option_id) as overlap
      from data a
      join data b on
        a.emp_id < b.emp_id and
        a.option_id = b.option_id
      group by a.emp_id, b.emp_id
    )
    select *
    from overlaps
    where overlap = (
      select max(overlap)
      from overlaps
    )
    
    def similarities(arr, max_diff)
      arr.combination(2)
         .map do |h1,h2|
           [[h1["id"], h2["id"]],
            count_similar(h1["opt_ids"], h2["opt_ids"], max_diff)]
          end.to_h
    end
    
    similarities(arr, max_diff)
      #=> {[11486, 12624]=> 9, [11486, 14588]=>0, [11486, 14589]=> 7, [11486, 14590]=>0,
      #    [11486, 14591]=>13, [11486, 14592]=>0, [11486, 14593]=> 0, [12624, 14588]=>4,
      #    [12624, 14589]=> 7, [12624, 14590]=>4, [12624, 14591]=>10, [12624, 14592]=>0,
      #    [12624, 14593]=> 0, [14588, 14589]=>6, [14588, 14590]=>14, [14588, 14591]=>0,
      #    [14588, 14592]=> 0, [14588, 14593]=>0, [14589, 14590]=> 6, [14589, 14591]=>7,
      #    [14589, 14592]=> 0, [14589, 14593]=>0, [14590, 14591]=> 0, [14590, 14592]=>0,
      #    [14590, 14593]=> 0, [14591, 14592]=>0, [14591, 14593]=> 0, [14592, 14593]=>0}
    
    similarities(arr, max_diff).max_by(5, &:last)
      #=> [[[14588, 14590], 14], [[11486, 14591], 13], [[12624, 14591], 10],
      #    [[11486, 12624],  9], [[12624, 14589],  7]]
    
    select
      a.emp_id emp_id1,
      b.emp_id emp_id2,
      count(a.option_id) as overlap
    from data a
    join data b on
      -- Ensure we count each pair only once
      a.emp_id < b.emp_id and
      a.option_id = b.option_id
    group by a.emp_id, b.emp_id
    
    with overlaps as (
      select
        a.emp_id emp_id1,
        b.emp_id emp_id2,
        count(a.option_id) as overlap
      from data a
      join data b on
        a.emp_id < b.emp_id and
        a.option_id = b.option_id
      group by a.emp_id, b.emp_id
    )
    select *
    from overlaps
    where overlap = (
      select max(overlap)
      from overlaps
    )
    
    create index idx_option_emp_ids on data(option_id, emp_id);