【问题标题】:Ruby Array - quick way to count overlapRuby Array - 计算重叠的快速方法
【发布时间】:2012-01-04 11:11:51
【问题描述】:

我正在使用我的一个模型中的序列化数组字段,特别是计算每个数组的共享成员数。

现在,根据我项目的性质,我必须进行大量的重叠计数。所以我想知道是否有一种超级快速、更灵活的方法来做到这一点。

目前,我使用的是 '&' 方法,所以我的代码如下所示

(user1.follower_names & user2.follower_names).count

效果很好......但我希望可能有更快的方法来做到这一点。

【问题讨论】:

  • 我不确定是否有确切的 Ruby 等价物,但在 python 中有一个内置类型 Set。您可以添加所有关注者,然后获取其长度/数量。其他人可能知道 ruby​​ 方式,以及您可以期待什么样的性能。

标签: mysql ruby-on-rails ruby intersection overlap


【解决方案1】:

为此设置更快。

require 'benchmark'
require 'set'
alphabet = ('a'..'z').to_a
user1_followers = 100.times.map{ alphabet.sample(3) }
user2_followers = 100.times.map{ alphabet.sample(3) }
user1_followers_set = user1_followers.to_set
user2_followers_set = user2_followers.to_set

n = 1000
Benchmark.bm(7) do |x|
  x.report('arrays'){ n.times{ (user1_followers & user2_followers).size } }
  x.report('set'){ n.times{ (user1_followers_set & user2_followers_set).size } }
end

输出:

              user     system      total        real
arrays    0.910000   0.000000   0.910000 (  0.926098)
set       0.350000   0.000000   0.350000 (  0.359571)

【讨论】:

  • 我有点担心将数组转换为集合所需的时间。这可以忽略不计吗?我的数组长度在 0-3000 之间。
  • 不,这不可忽略;在这台古董笔记本电脑上,两次转换设置(1000 次)以及实际的交叉点操作大约需要 1 秒。但是在将 user_follower 与多个关注者进行比较的情况下,如果您将集合存储(在内存中)并且关注者的数量大于 1,则您开始赢得时间。换句话说,不要转换两次。
  • 刚刚运行了一些数字......看起来使用集合实际上更慢,因为只是转换为集合花了很长时间。我想我可能能够将我所有的数据结构更改为序列化集,在这一点上,它会快得多。
【解决方案2】:

上述方法的替代方法是在数组上使用“-”运算符:

user1.follower_names.size - (user1.follower_names - user2.follower_names).size

本质上,这得到了列表一的大小,并减去了没有交集的联合列表的大小。这不如使用集合快,但比单独使用与数组的交集要快得多

【讨论】:

  • 事实证明它的速度非常低(大约 1/100000 秒),但无论我运行多少次,它都会快一点.. 所以我给了你一个赞成票 = ]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 2019-06-25
  • 2015-01-15
  • 2018-09-18
  • 2011-04-13
  • 2010-12-17
  • 1970-01-01
相关资源
最近更新 更多