Let’s say I have this array with shipments ids.
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
i = Invoice.find(:all, :select => "id, shipment_id") [#<Invoice id: 98, shipment_id: 2>, #<Invoice id: 99, shipment_id: 3>]
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.
To get the difference between two arrays: Use the filter() method to iterate over the first array. Check if each element is not contained in the second array. Repeat the steps, but this time iterate over the second array.
We already know Array#intersection or Array#& methods which are used to find the common elements between arrays. The intersection or & methods return an empty array or array having the common elements in it as result.
This is another way to do this: use the Array#index method. It returns the index of the first occurrence of the element in the array. This returns the index of the first word in the array that contains the letter 'o'. index still iterates over the array, it just returns the value of the element.
a = [2, 4, 6, 8] b = [1, 2, 3, 4] a - b | b - a # => [6, 8, 1, 3]
First you would get a list of shipping_id's that appear in invoices:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With