# Return values from array A in the order they are in array B

So my question is the cleanest way to do #product_panels_for below:

class ProductPanel < Struct.new(:product)
end

class ProductPresenter
def product_panels_for(selected_products)
selected_products.map do |product|
product_panels.find { |panel| panel.product.to_s == product }
end.
compact
end

def product_panels
end
end



This is obviously simplified, but the point is #product_panels_for should return values from product_panels but in the order given in selected_panels. Maybe this is fine is just feels a bit gangly for something that seems conceptually simpler than that.

To be clear the order is defined by the business, it won't be alphabetical or anything nice.

In case anyone's thinking it, yes, I know in Ruby 2.7 I could replace .map...compact with .filter_map, but I'm not on 2.7 yet.

My previous implementation was:

def product_panels_for(selected_products)
product_panels.select { |pp| selected_products.include?(pp) }
end


which was nice and clean but didn't preserve the order of selected_products.

If the implementation at the top can't be improved on, is there a nice way to use this previous implementation but chain something after the select that sorts the result so the order matches selected_products? I'm just generally curious about a good way to cleanly sort A so its order matches B where B is a list of values for an attributes of A.

• Did you notice that if you have duplicate products you only get one product panel? If you are assuming a 1-to- relationship then that's probably fine... – Garrett Motzner Apr 3 at 1:29

Also, I don't think it is worth adding one more step to order it just to use select`.