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 &lt; 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
    [ProductPanel.new(:iphone), ProductPanel.new(:ipad), ProductPanel.new(:ibidet)]
  end
end

ProductPresenter.new.product_panels_for(['ipad', 'iphone']) # =&gt; [&lt;ProductPanel product=:ipad&gt;, &lt;ProductPanel product=:iphone&gt;]


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.
Your solution looks good to me, I tried some alternatives but they end up being a little more verbose and not adding value that makes it worth.

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

I would go with your first solution.