web-dev-qa-db-ja.com

Rails 3. 2つの配列の違いを取得するには?

出荷IDを持つこの配列があるとします。

s = Shipment.find(:all, :select => "id")

[#<Shipment id: 1>, #<Shipment id: 2>, #<Shipment id: 3>, #<Shipment id: 4>, #<Shipment id: 5>]

出荷IDの請求書の配列

i = Invoice.find(:all, :select => "id, shipment_id")

[#<Invoice id: 98, shipment_id: 2>, #<Invoice id: 99, shipment_id: 3>]
  • 請求書は出荷に属します。
  • 出荷には請求書が1つあります。
  • そのため、請求書テーブルにはshipment_id

請求書を作成するには、[新規請求書]をクリックします。次に、[出荷]の選択メニューがあります。[請求書を作成する出荷]を選択できます。そのため、請求書が作成されていない出荷のリストのみを表示したいと思います。

だから、まだ請求書がない荷物の配列が必要です。上記の例では、答えは1、4、5になります。

48
leonel

最初に、請求書に表示されるshipping_idのリストを取得します。

ids = i.map{|x| x.shipment_id}

次に、元の配列からそれらを「拒否」します。

s.reject{|x| ids.include? x.id}

注: rejectは新しい配列を返すことに注意してください。rejectを使用してください。元の配列を変更する場合

40
pguardiario
a = [2, 4, 6, 8]
b = [1, 2, 3, 4]

a - b | b - a # => [6, 8, 1, 3]
115
Kyle Decot

代替記号を使用

irb(main):001:0> [1, 2, 3, 2, 6, 7] - [2, 1]
=> [3, 6, 7]
20
denis.peplin

Ruby 2.6はArray.differenceを導入しています:

[1, 1, 2, 2, 3, 3, 4, 5 ].difference([1, 2, 4]) #=> [ 3, 3, 5 ]

したがって、ここに示されている場合:

Shipment.pluck(:id).difference(Invoice.pluck(:shipment_id))

問題に対する素敵でエレガントな解決策のようです。私はa - b | b - aの熱心なフォロワーでしたが、時々思い出すのは難しいかもしれません。

これは確かにそれを大事にします。

5
SRack

これは、1つのActiveRecordクエリで実行する必要があります

_Shipment.where(["id NOT IN (?)", Invoice.select(:shipment_id)]).select(:id)
_

そして、それはSQLを出力します

_SELECT "shipments"."id" FROM "shipments"  WHERE (id NOT IN (SELECT "invoices"."shipment_id" FROM "invoices"))
_

Rails 4 +では、次のことができます

_Shipment.where.not(id: Invoice.select(:shipment_id).distinct).select(:id)
_

そして、それはSQLを出力します

_SELECT "shipments"."id" FROM "shipments"  WHERE ("shipments"."id" NOT IN (SELECT DISTINCT "invoices"."shipment_id" FROM "invoices"))
_

そして、select(:id)の代わりに、idsメソッドをお勧めします。

_Shipment.where.not(id: Invoice.select(:shipment_id).distinct).ids
_
5
6ft Dan

ここでのpgquardiarioからの以前の回答には、一方向の違いのみが含まれていました。両方の配列との違いが必要な場合(両方に固有のアイテムがあるため)、次のようなものを試してください。

def diff(x,y)
  o = x
  x = x.reject{|a| if y.include?(a); a end }
  y = y.reject{|a| if o.include?(a); a end }
  x | y
end
5
6ft Dan

Pure Rubyソリューションは

(a + b) - (a & b)

([1,2,3,4] + [1,3]) - ([1,2,3,4] & [1,3])
=> [2,4]

どこa + bは2つの配列の和集合を生成します
そしてa & b交差点を返す
そしてunion - intersectionは差を返します

2
zhisme