有没有办法在ruby中重构以下代码
我已经写了一段代码,需要重构它有没有办法在ruby中重构以下代码,ruby,ruby-on-rails-5,Ruby,Ruby On Rails 5,我已经写了一段代码,需要重构它 Reviewing.where(reviewing_status_condition(employee_ids)).group(:employee_id).count.map{ |employee_id, reviewings_count_per_employee| employee_id if reviewings_count_per_employee >= @cycle.min_required_anon_feedback }.compac
Reviewing.where(reviewing_status_condition(employee_ids)).group(:employee_id).count.map{
|employee_id, reviewings_count_per_employee|
employee_id if reviewings_count_per_employee >= @cycle.min_required_anon_feedback
}.compact
有人能帮忙吗?对我来说,第一步是将
where
子句和group
移动到指定的范围。这将减少最初的部分:
Reviewing.where(reviewing_status_condition(employee_ids)).group(:employee_id).count
更像是:
Reviewing.reviewing_count(reviewing_status_condition(employee_ids))
这并不是很短,但确实显著改善了实现与执行的分离
第二步取决于您使用的Ruby版本。在2.7版本之前,执行map
和compact
步骤的正确方法是使用select
和map
执行您已经或可以执行的操作,而Ruby 2.7引入了filter\u map
,这是您在这里拥有的操作的一个单步组合
请参阅“”,以了解有关
filter\u map
的更多详细信息,您也可以选择让数据库处理此问题,而不是用Ruby解决此问题。然而,要做到这一点,您首先需要知道您的查询将是什么,我会选择以下内容:
选择reviewings.employee\u id
来自评论
哪里
按reviewings.employee\u id分组
拥有计数(reviewings.id)>=
这可以通过以下代码实现:
reviewings = Reviewing.arel_table
employee_ids = Reviewing
.where(reviewing_status_condition(employee_ids))
.group(:employee_id)
.having(reviewings[:id].count.gteq(@cycle.min_required_anon_feedback))
.pluck(:employee_id)
通过限制从数据库返回的数据,您可以省去Ruby端的数据操作
如果你想了解更多关于阿雷尔的信息,我建议你看看他们的网站
让我添加一个有趣的比较。假设你要点一些比萨饼
- 你现在正在做以下事情:你打电话给你的比萨饼店,让他们每送一个比萨饼。当比萨饼到达你家时,你和你的同志们需要在吃比萨饼之前弄清楚要保留什么比萨饼,扔掉什么比萨饼
- 我的建议是:看看菜单,弄清楚你需要什么样的比萨饼。只订购你需要的东西。当比萨饼到达你家时,所有的决定都已经做出并得到了处理(假设送货正确),你就可以享受你的比萨饼了
.map{…}.compact
更改为.select{…}.keys
,因为它可以更好地传达您试图通过代码实现的目标。您正在根据审核计数筛选/选择某些员工ID
reviewings_count_per_employee = Reviewing.where(reviewing_status_condition(employee_ids)).group(:employee_id).count
我不确定这是否降低了时间复杂度,但它确实提高了可读性。只要你处于线性领域,我就不会太担心时间的复杂性。如果select
isO(N)
和键isO(N)
,那么您最终得到的O(2N)
不是真正的问题。如果你想保留你的代码O(N)
,下面就可以了
employee_ids = []
reviewings_count_per_employee.each do |id, count|
employee_ids << id if count >= @cycle.min_required_anon_feedback
end
employee_id=[]
审核每名员工的人数。每名员工的id、计数
员工ID=@cycle.min\u需要反馈
结束
但是,我个人认为使用select
的解决方案比每个解决方案更具可读性。虽然这可能会节省一些CPU负载,当你重新审视代码时,你的大脑必须更加努力地理解你在6-12个月内写的东西。你希望通过这种重构实现什么?减少映射和压缩带来的时间复杂性。你是否在重构之前测试过这段代码并确保它实际工作?我可以想象,.count.map
是有问题的,因为.count
创建了一个计数查询并返回一个整数-但是你在它上面调用map就像调用一个集合一样。没有可能减少map的使用,然后只使用一个枚举器方法来解决这个问题吗?@mahehmesta我添加了寻址这是红宝石的。回答得好。花时间尝试用Ruby修复迭代很可能完全是浪费时间,因为问题实际上是首先将所有数据从数据库中取出。
employee_ids = []
reviewings_count_per_employee.each do |id, count|
employee_ids << id if count >= @cycle.min_required_anon_feedback
end