Rails 3。如何获得两个数组之间的差异?

时间:2021-10-12 21:30:01

Let’s say I have this array with shipments ids.

假设我有一个带有装运id的数组。

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

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

Array of invoices with shipment id's

带有发货id的发票

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

[#<Invoice id: 98, shipment_id: 2>, #<Invoice id: 99, shipment_id: 3>]
  • Invoices belongs to Shipment.
  • 发票属于装运。
  • Shipment has one Invoice.
  • 货物有一个发票。
  • So the invoices table has a column of shipment_id.
  • 所以发票表有一列shipment_id。

To create an invoice, I click on New Invoice, then there is a select menu with Shipments, so I can choose "which shipment am i creating the invoice for". So I only want to display a list of shipments that an invoice hasn't been created for.

为了创建发票,我点击新的发票,然后有一个带有发货的选择菜单,所以我可以选择“我为哪个货物创建发票”。因此,我只想显示一个未创建发票的发货列表。

So I need an array of Shipments that don't have an Invoice yet. In the example above, the answer would be 1, 4, 5.

所以我需要一大堆没有发票的货物。在上面的例子中,答案是1 4 5。

5 个解决方案

#1


35  

First you would get a list of shipping_id's that appear in invoices:

首先,您将得到发票中出现的shipping_id列表:

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

Then 'reject' them from your original array:

然后从原始数组中“拒绝”它们:

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

Note: remember that reject returns a new array, use reject! if you want to change the original array

注意:记住,拒绝返回一个新的数组,使用拒绝!如果要更改原始数组

#2


96  

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

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

#3


20  

Use substitute sign

使用替代符号

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

#4


5  

The previous answer here from pgquardiario only included a one directional difference. If you want the difference from both arrays (as in they both have a unique item) then try something like the following.

之前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


4  

This should do it in one ActiveRecord query

这应该在一个ActiveRecord查询中完成。

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

And it outputs the SQL

它输出SQL

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

In Rails 4+ you can do the following

在Rails 4+中,您可以执行以下操作

Shipment.where.not(id: Invoice.select(:shipment_id).distinct).select(:id)

And it outputs the SQL

它输出SQL

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

And instead of select(:id) I recommend the ids method.

我建议使用ids方法代替select(:id)。

Shipment.where.not(id: Invoice.select(:shipment_id).distinct).ids

#1


35  

First you would get a list of shipping_id's that appear in invoices:

首先,您将得到发票中出现的shipping_id列表:

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

Then 'reject' them from your original array:

然后从原始数组中“拒绝”它们:

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

Note: remember that reject returns a new array, use reject! if you want to change the original array

注意:记住,拒绝返回一个新的数组,使用拒绝!如果要更改原始数组

#2


96  

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

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

#3


20  

Use substitute sign

使用替代符号

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

#4


5  

The previous answer here from pgquardiario only included a one directional difference. If you want the difference from both arrays (as in they both have a unique item) then try something like the following.

之前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


4  

This should do it in one ActiveRecord query

这应该在一个ActiveRecord查询中完成。

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

And it outputs the SQL

它输出SQL

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

In Rails 4+ you can do the following

在Rails 4+中,您可以执行以下操作

Shipment.where.not(id: Invoice.select(:shipment_id).distinct).select(:id)

And it outputs the SQL

它输出SQL

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

And instead of select(:id) I recommend the ids method.

我建议使用ids方法代替select(:id)。

Shipment.where.not(id: Invoice.select(:shipment_id).distinct).ids