出荷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>]
shipment_id
。請求書を作成するには、[新規請求書]をクリックします。次に、[出荷]の選択メニューがあります。[請求書を作成する出荷]を選択できます。そのため、請求書が作成されていない出荷のリストのみを表示したいと思います。
だから、まだ請求書がない荷物の配列が必要です。上記の例では、答えは1、4、5になります。
最初に、請求書に表示されるshipping_idのリストを取得します。
ids = i.map{|x| x.shipment_id}
次に、元の配列からそれらを「拒否」します。
s.reject{|x| ids.include? x.id}
注: rejectは新しい配列を返すことに注意してください。rejectを使用してください。元の配列を変更する場合
a = [2, 4, 6, 8]
b = [1, 2, 3, 4]
a - b | b - a # => [6, 8, 1, 3]
代替記号を使用
irb(main):001:0> [1, 2, 3, 2, 6, 7] - [2, 1]
=> [3, 6, 7]
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
の熱心なフォロワーでしたが、時々思い出すのは難しいかもしれません。
これは確かにそれを大事にします。
これは、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
_
ここでの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
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
は差を返します