aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Ebeling <florian.ebeling@gmail.com>2018-09-27 10:19:08 +0200
committerFlorian Ebeling <florian.ebeling@gmail.com>2018-11-06 17:56:58 +0100
commitf9157587c9d61a0e24a0dcba7b31aa698ddeb641 (patch)
treec66767b93098e9e8c614431438e134c262e14878
parent11bad94237b17c078eb5cac8557e9ed9e37ec274 (diff)
downloadrails-f9157587c9d61a0e24a0dcba7b31aa698ddeb641.tar.gz
rails-f9157587c9d61a0e24a0dcba7b31aa698ddeb641.tar.bz2
rails-f9157587c9d61a0e24a0dcba7b31aa698ddeb641.zip
Optimize difference and intersection
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb26
1 files changed, 9 insertions, 17 deletions
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 8a8149b777..2322a49931 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -164,32 +164,24 @@ module ActiveRecord
end
def difference(a, b)
- set_a = as_set(a)
- set_b = as_set(b)
+ distribution = distribution(b)
- from_set(set_a - set_b)
+ a.reject { |record| mark_occurrence(distribution, record) }
end
def intersection(a, b)
- set_a = as_set(a)
- set_b = as_set(b)
+ distribution = distribution(b)
- from_set(set_a & set_b)
+ a.select { |record| mark_occurrence(distribution, record) }
end
- def as_set(records)
- records.zip(occurences(records))
+ def mark_occurrence(distribution, record)
+ distribution[record] > 0 && distribution[record] -= 1
end
- def from_set(record_set)
- record_set.map(&:first)
- end
-
- def occurences(array)
- counts = Hash.new(0)
-
- array.map do |object|
- counts[object] += 1
+ def distribution(array)
+ array.each_with_object(Hash.new(0)) do |record, distribution|
+ distribution[record] += 1
end
end