附加具有唯一值的collect数组

时间:2012-09-01 19:16:20

标签: ruby arrays collect

所以我有一个由collect构建的数组。

@a = Relation.where(part: "v04")

@relations = @a.collect {|x| x.car}

构建..

  

=> [“f03”,“f04”]

@a = Relation.where(part: "v03")

@relations = @a.collect {|x| x.car}

构建..

  

=> [“f01”,“f03”]

我想要的是附加收集,以便我可以从v03和v04构建一个数组,使它看起来像这样。

  

=> [“f03”,“f04”,“f01”,“f03”]

然后只保留唯一值,使其看起来像这样。

  

=> [“f03”,“f04”,“f01”]

因为它被列出两次而取出f03。

4 个答案:

答案 0 :(得分:19)

["f03", "f04"] | ["f01", "f03"] #=> ["f03", "f04", "f01"]

car1 = ["f03", "f04"]
car2 = ["f01", "f03"]

car1 | car2 #=> ["f03", "f04", "f01"]

答案 1 :(得分:3)

@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

如果您使用的是rails 3.2

parts = ['v03','v04']
@relations = Relation.where(part: parts).pluck(:name).uniq

在rails 3中,我认为这应该有效

@relations  = Relation.where(part: parts).collect(&:name).uniq  

答案 2 :(得分:3)

这是执行此操作的最佳方式:Relation.where(part: ['v03', 'v04']).uniq.pluck(:car)

以下是一个完整的例子:

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"]

一些想法:

不要将变量放在变量前面,除非你希望它们是实例变量(例如@a应该明显是a - 即使这样,一个更好的名字也会很好。我如上所示,它可能完全摆脱它。)

最好使用pluck而不是map,因为pluck只选择相关数据:SELECT car FROM "relations" WHERE "relations"."part" = 'v04' vs SELECT "relations".* FROM "relations" WHERE "relations"."part" = 'v04'

最好在ActiveRecord :: Relation上使用.uniq,因为它将唯一性移动到数据库中,而不是尝试使用Ruby在内存中执行它:SELECT DISTINCT car FROM "relations" WHERE "relations"."part" IN ('v03', 'v04')

答案 3 :(得分:2)

为什么不将where个调用合并为一个?

cars = Relation.where(part: ['v03', 'v04']).map(&:car).uniq

或可能

car_ids = Relation.where(part: ['v03', 'v04']).select('DISTINCT car_id').map(&:car_id)
cars = Car.where(id: car_ids)

第一个在Ruby中工作更多,第二个在SQL中工作。