Appending a collect array with unique values
Question
So I have an array built by collect.
@a = Relation.where(part: "v04")
@relations = @a.collect {|x| x.car}
Builds..
=> ["f03", "f04"]
@a = Relation.where(part: "v03")
@relations = @a.collect {|x| x.car}
Builds..
=> ["f01", "f03"]
What I want is to append the collect so that I can build an array from both v03 and v04 so that it looks like this.
=> ["f03", "f04", "f01", "f03"]
And then only keeps unique values so that it looks like this.
=> ["f03", "f04", "f01"]
Take out f03 since it was listed twice.
Solution
["f03", "f04"] | ["f01", "f03"] #=> ["f03", "f04", "f01"]
car1 = ["f03", "f04"]
car2 = ["f01", "f03"]
car1 | car2 #=> ["f03", "f04", "f01"]
OTHER TIPS
@a = Relation.where(part: "v04")
@relations1 = @a.collect {|x| x.car}
@a = Relation.where(part: "v03")
@relations2 = @a.collect {|x| x.car}
@all_relations = @relations2 | @relations2
If you are using rails 3.2
parts = ['v03','v04']
@relations = Relation.where(part: parts).pluck(:name).uniq
In rails 3 I think this should work
@relations = Relation.where(part: parts).collect(&:name).uniq
This is the best way to do this: Relation.where(part: ['v03', 'v04']).uniq.pluck(:car)
Here's a full example:
require 'active_record'
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
ActiveRecord::Schema.define do
self.verbose = false
create_table :relations do |t|
t.string :part
t.string :car
end
end
Relation = Class.new ActiveRecord::Base
# build the relations (btw, this name makes no sense)
Relation.create! car: 'f01', part: 'v03'
Relation.create! car: 'f03', part: 'v03'
Relation.create! car: 'f03', part: 'v04'
Relation.create! car: 'f04', part: 'v04'
# querying
Relation.where(part: "v04").pluck(:car) # => ["f03", "f04"]
Relation.where(part: "v03").pluck(:car) # => ["f01", "f03"]
Relation.where(part: ['v03', 'v04']).uniq.pluck(:car) # => ["f01", "f03", "f04"]
Some thoughts:
Don't put asperands in front of your variables unless you want them to be instance variables (e.g. @a
should clearly be a
-- and even then, a better name would be good. I'd probably get rid of it altogether as shown above).
It is better to use pluck than map, because pluck only selects the relevant data: SELECT car FROM "relations" WHERE "relations"."part" = 'v04'
vs
SELECT "relations".* FROM "relations" WHERE "relations"."part" = 'v04'
It is better to use .uniq
on the ActiveRecord::Relation because it moves the uniqueness into the database rather than trying to do it in memory with Ruby: SELECT DISTINCT car FROM "relations" WHERE "relations"."part" IN ('v03', 'v04')
Why not combine the where
calls into one?
cars = Relation.where(part: ['v03', 'v04']).map(&:car).uniq
or possibly
car_ids = Relation.where(part: ['v03', 'v04']).select('DISTINCT car_id').map(&:car_id)
cars = Car.where(id: car_ids)
The first does more work in Ruby, the second in SQL.