build a new array of hash from multiple array of hashes












0















I have following three array of hashes.



customer_mapping = [
{:customer_id=>"a", :customer_order_id=>"g1"},
{:customer_id=>"b", :customer_order_id=>"g2"},
{:customer_id=>"c", :customer_order_id=>"g3"},
{:customer_id=>"d", :customer_order_id=>"g4"},
{:customer_id=>"e", :customer_order_id=>"g5"}
]

customer_with_products = [
{:customer_order_id=>"g1", :product_order_id=>"a1"},
{:customer_order_id=>"g2", :product_order_id=>"a2"},
{:customer_order_id=>"g3", :product_order_id=>"a3"},
{:customer_order_id=>"g4", :product_order_id=>"a4"},
{:customer_order_id=>"g5", :product_order_id=>"a5"}
]

product_mapping = [
{:product_id=>"j", :product_order_id=>"a1"},
{:product_id=>"k", :product_order_id=>"a2"},
{:product_id=>"l", :product_order_id=>"a3"}
]


What i want is a new hash with only customer_id and product_id



{:product_id=>"j", :customer_id=>"a"},
{:product_id=>"k", :customer_id=>"b"},
{:product_id=>"l", :customer_id=>"c"}


I tried to loop over product_mapping and select the customer_order_id that match product_order_id in customer_with_products and then thought of looping over customer_mapping but not able to get desired output from the first step.



How can i achieve this?










share|improve this question



























    0















    I have following three array of hashes.



    customer_mapping = [
    {:customer_id=>"a", :customer_order_id=>"g1"},
    {:customer_id=>"b", :customer_order_id=>"g2"},
    {:customer_id=>"c", :customer_order_id=>"g3"},
    {:customer_id=>"d", :customer_order_id=>"g4"},
    {:customer_id=>"e", :customer_order_id=>"g5"}
    ]

    customer_with_products = [
    {:customer_order_id=>"g1", :product_order_id=>"a1"},
    {:customer_order_id=>"g2", :product_order_id=>"a2"},
    {:customer_order_id=>"g3", :product_order_id=>"a3"},
    {:customer_order_id=>"g4", :product_order_id=>"a4"},
    {:customer_order_id=>"g5", :product_order_id=>"a5"}
    ]

    product_mapping = [
    {:product_id=>"j", :product_order_id=>"a1"},
    {:product_id=>"k", :product_order_id=>"a2"},
    {:product_id=>"l", :product_order_id=>"a3"}
    ]


    What i want is a new hash with only customer_id and product_id



    {:product_id=>"j", :customer_id=>"a"},
    {:product_id=>"k", :customer_id=>"b"},
    {:product_id=>"l", :customer_id=>"c"}


    I tried to loop over product_mapping and select the customer_order_id that match product_order_id in customer_with_products and then thought of looping over customer_mapping but not able to get desired output from the first step.



    How can i achieve this?










    share|improve this question

























      0












      0








      0








      I have following three array of hashes.



      customer_mapping = [
      {:customer_id=>"a", :customer_order_id=>"g1"},
      {:customer_id=>"b", :customer_order_id=>"g2"},
      {:customer_id=>"c", :customer_order_id=>"g3"},
      {:customer_id=>"d", :customer_order_id=>"g4"},
      {:customer_id=>"e", :customer_order_id=>"g5"}
      ]

      customer_with_products = [
      {:customer_order_id=>"g1", :product_order_id=>"a1"},
      {:customer_order_id=>"g2", :product_order_id=>"a2"},
      {:customer_order_id=>"g3", :product_order_id=>"a3"},
      {:customer_order_id=>"g4", :product_order_id=>"a4"},
      {:customer_order_id=>"g5", :product_order_id=>"a5"}
      ]

      product_mapping = [
      {:product_id=>"j", :product_order_id=>"a1"},
      {:product_id=>"k", :product_order_id=>"a2"},
      {:product_id=>"l", :product_order_id=>"a3"}
      ]


      What i want is a new hash with only customer_id and product_id



      {:product_id=>"j", :customer_id=>"a"},
      {:product_id=>"k", :customer_id=>"b"},
      {:product_id=>"l", :customer_id=>"c"}


      I tried to loop over product_mapping and select the customer_order_id that match product_order_id in customer_with_products and then thought of looping over customer_mapping but not able to get desired output from the first step.



      How can i achieve this?










      share|improve this question














      I have following three array of hashes.



      customer_mapping = [
      {:customer_id=>"a", :customer_order_id=>"g1"},
      {:customer_id=>"b", :customer_order_id=>"g2"},
      {:customer_id=>"c", :customer_order_id=>"g3"},
      {:customer_id=>"d", :customer_order_id=>"g4"},
      {:customer_id=>"e", :customer_order_id=>"g5"}
      ]

      customer_with_products = [
      {:customer_order_id=>"g1", :product_order_id=>"a1"},
      {:customer_order_id=>"g2", :product_order_id=>"a2"},
      {:customer_order_id=>"g3", :product_order_id=>"a3"},
      {:customer_order_id=>"g4", :product_order_id=>"a4"},
      {:customer_order_id=>"g5", :product_order_id=>"a5"}
      ]

      product_mapping = [
      {:product_id=>"j", :product_order_id=>"a1"},
      {:product_id=>"k", :product_order_id=>"a2"},
      {:product_id=>"l", :product_order_id=>"a3"}
      ]


      What i want is a new hash with only customer_id and product_id



      {:product_id=>"j", :customer_id=>"a"},
      {:product_id=>"k", :customer_id=>"b"},
      {:product_id=>"l", :customer_id=>"c"}


      I tried to loop over product_mapping and select the customer_order_id that match product_order_id in customer_with_products and then thought of looping over customer_mapping but not able to get desired output from the first step.



      How can i achieve this?







      ruby-on-rails ruby






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 21 '18 at 17:57









      jose milianojose miliano

      384




      384
























          5 Answers
          5






          active

          oldest

          votes


















          2














          Using



          def merge_by(a,b, key)
          (a+b).group_by { |h| h[key] }
          .each_value.map { |arr| arr.inject(:merge) }
          end

          merge_by(
          merge_by(customer_mapping, customer_with_products, :customer_order_id),
          product_mapping,
          :product_order_id
          ).select { |h| h[:product_id] }.map { |h| h.slice(:product_id, :customer_id) }

          #=>[{:product_id=>"j", :customer_id=>"a"},
          # {:product_id=>"k", :customer_id=>"b"},
          # {:product_id=>"l", :customer_id=>"c"}]


          Definitely not the cleanest solution, if your initial arrays come from SQL queries, I think those queries could be modified to aggregate your data properly.



          merge_by(customer_mapping, customer_with_products, :customer_order_id)
          # => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
          # {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
          # {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
          # {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
          # {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]


          Then merge it similarly with your last array and cleanup the result selecting only the elements for which :product_id was found, slicing wanted keys.



          Alternatively, a much more readable solution, depending on your array sizes might be slower as it keeps iterating over the hashes:



          product_mapping.map do |hc| 
          b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
          a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
          [hc, a_match, b_match].inject(:merge)
          end.map { |h| h.slice(:product_id, :customer_id) }





          share|improve this answer

































            1














            Following your handling of the problem the solution would be the following:



            result_hash_array = product_mapping.map do |product_mapping_entry|
            customer_receipt = customer_with_products.find do |customer_with_products_entry|
            product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
            end
            customer_id = customer_mapping.find do |customer_mapping_entry|
            customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
            end[:customer_id]
            {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
            end


            Output



            results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
            {:product_id=>"k", :customer_id=>"b"},
            {:product_id=>"l", :customer_id=>"c"}]





            share|improve this answer

































              0














              Other option, starting from customer_mapping, one liner (but quite wide):



              customer_mapping.map { |e| {customer_id: e[:customer_id], product_id: (product_mapping.detect { |k| k[:product_order_id] == (customer_with_products.detect{ |h| h[:customer_order_id] == e[:customer_order_id] } || {} )[:product_order_id] } || {} )[:product_id]  } }

              #=> [{:customer_id=>"a", :product_id=>"j"},
              # {:customer_id=>"b", :product_id=>"k"},
              # {:customer_id=>"c", :product_id=>"l"},
              # {:customer_id=>"d", :product_id=>nil},
              # {:customer_id=>"e", :product_id=>nil}]





              share|improve this answer

































                0














                cust_order_id_to_cust_id =
                customer_mapping.each_with_object({}) do |g,h|
                h[g[:customer_order_id]] = g[:customer_id]
                end
                #=> {"g1"=>"a", "g2"=>"b", "g3"=>"c", "g4"=>"d", "g5"=>"e"}

                prod_order_id_to_cust_order_id =
                customer_with_products.each_with_object({}) do |g,h|
                h[g[:product_order_id]] = g[:customer_order_id]
                end
                #=> {"a1"=>"g1", "a2"=>"g2", "a3"=>"g3", "a4"=>"g4", "a5"=>"g5"}

                product_mapping.map do |h|
                { product_id: h[:product_id], customer_id:
                cust_order_id_to_cust_id[prod_order_id_to_cust_order_id[h[:product_order_id]]] }
                end
                #=> [{:product_id=>"j", :customer_id=>"a"},
                # {:product_id=>"k", :customer_id=>"b"},
                # {:product_id=>"l", :customer_id=>"c"}]


                This formulation is particularly easy to test. (It's so straightforward that no debugging was needed).






                share|improve this answer

































                  0














                  I would recommended to rather take a longer but more readable solution which you also understand in some months from now by looking at it. Use full names for the hash keys instead of hiding them behind k, v for more complexe lookups (maybe its just my personal preference).



                  I would suggest somethink like:



                  result = product_mapping.map do |mapping|
                  customer_id = customer_mapping.find do |hash|
                  hash[:customer_order_id] == customer_with_products.find do |hash|
                  hash[:product_order_id] == mapping[:product_order_id]
                  end[:customer_order_id]
                  end[:customer_id]

                  { product_id: mapping[:product_id], customer_id: customer_id }
                  end





                  share|improve this answer























                    Your Answer






                    StackExchange.ifUsing("editor", function () {
                    StackExchange.using("externalEditor", function () {
                    StackExchange.using("snippets", function () {
                    StackExchange.snippets.init();
                    });
                    });
                    }, "code-snippets");

                    StackExchange.ready(function() {
                    var channelOptions = {
                    tags: "".split(" "),
                    id: "1"
                    };
                    initTagRenderer("".split(" "), "".split(" "), channelOptions);

                    StackExchange.using("externalEditor", function() {
                    // Have to fire editor after snippets, if snippets enabled
                    if (StackExchange.settings.snippets.snippetsEnabled) {
                    StackExchange.using("snippets", function() {
                    createEditor();
                    });
                    }
                    else {
                    createEditor();
                    }
                    });

                    function createEditor() {
                    StackExchange.prepareEditor({
                    heartbeatType: 'answer',
                    autoActivateHeartbeat: false,
                    convertImagesToLinks: true,
                    noModals: true,
                    showLowRepImageUploadWarning: true,
                    reputationToPostImages: 10,
                    bindNavPrevention: true,
                    postfix: "",
                    imageUploader: {
                    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                    allowUrls: true
                    },
                    onDemand: true,
                    discardSelector: ".discard-answer"
                    ,immediatelyShowMarkdownHelp:true
                    });


                    }
                    });














                    draft saved

                    draft discarded


















                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53418008%2fbuild-a-new-array-of-hash-from-multiple-array-of-hashes%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown

























                    5 Answers
                    5






                    active

                    oldest

                    votes








                    5 Answers
                    5






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes









                    2














                    Using



                    def merge_by(a,b, key)
                    (a+b).group_by { |h| h[key] }
                    .each_value.map { |arr| arr.inject(:merge) }
                    end

                    merge_by(
                    merge_by(customer_mapping, customer_with_products, :customer_order_id),
                    product_mapping,
                    :product_order_id
                    ).select { |h| h[:product_id] }.map { |h| h.slice(:product_id, :customer_id) }

                    #=>[{:product_id=>"j", :customer_id=>"a"},
                    # {:product_id=>"k", :customer_id=>"b"},
                    # {:product_id=>"l", :customer_id=>"c"}]


                    Definitely not the cleanest solution, if your initial arrays come from SQL queries, I think those queries could be modified to aggregate your data properly.



                    merge_by(customer_mapping, customer_with_products, :customer_order_id)
                    # => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
                    # {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
                    # {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
                    # {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
                    # {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]


                    Then merge it similarly with your last array and cleanup the result selecting only the elements for which :product_id was found, slicing wanted keys.



                    Alternatively, a much more readable solution, depending on your array sizes might be slower as it keeps iterating over the hashes:



                    product_mapping.map do |hc| 
                    b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
                    a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
                    [hc, a_match, b_match].inject(:merge)
                    end.map { |h| h.slice(:product_id, :customer_id) }





                    share|improve this answer






























                      2














                      Using



                      def merge_by(a,b, key)
                      (a+b).group_by { |h| h[key] }
                      .each_value.map { |arr| arr.inject(:merge) }
                      end

                      merge_by(
                      merge_by(customer_mapping, customer_with_products, :customer_order_id),
                      product_mapping,
                      :product_order_id
                      ).select { |h| h[:product_id] }.map { |h| h.slice(:product_id, :customer_id) }

                      #=>[{:product_id=>"j", :customer_id=>"a"},
                      # {:product_id=>"k", :customer_id=>"b"},
                      # {:product_id=>"l", :customer_id=>"c"}]


                      Definitely not the cleanest solution, if your initial arrays come from SQL queries, I think those queries could be modified to aggregate your data properly.



                      merge_by(customer_mapping, customer_with_products, :customer_order_id)
                      # => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
                      # {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
                      # {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
                      # {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
                      # {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]


                      Then merge it similarly with your last array and cleanup the result selecting only the elements for which :product_id was found, slicing wanted keys.



                      Alternatively, a much more readable solution, depending on your array sizes might be slower as it keeps iterating over the hashes:



                      product_mapping.map do |hc| 
                      b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
                      a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
                      [hc, a_match, b_match].inject(:merge)
                      end.map { |h| h.slice(:product_id, :customer_id) }





                      share|improve this answer




























                        2












                        2








                        2







                        Using



                        def merge_by(a,b, key)
                        (a+b).group_by { |h| h[key] }
                        .each_value.map { |arr| arr.inject(:merge) }
                        end

                        merge_by(
                        merge_by(customer_mapping, customer_with_products, :customer_order_id),
                        product_mapping,
                        :product_order_id
                        ).select { |h| h[:product_id] }.map { |h| h.slice(:product_id, :customer_id) }

                        #=>[{:product_id=>"j", :customer_id=>"a"},
                        # {:product_id=>"k", :customer_id=>"b"},
                        # {:product_id=>"l", :customer_id=>"c"}]


                        Definitely not the cleanest solution, if your initial arrays come from SQL queries, I think those queries could be modified to aggregate your data properly.



                        merge_by(customer_mapping, customer_with_products, :customer_order_id)
                        # => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
                        # {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
                        # {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
                        # {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
                        # {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]


                        Then merge it similarly with your last array and cleanup the result selecting only the elements for which :product_id was found, slicing wanted keys.



                        Alternatively, a much more readable solution, depending on your array sizes might be slower as it keeps iterating over the hashes:



                        product_mapping.map do |hc| 
                        b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
                        a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
                        [hc, a_match, b_match].inject(:merge)
                        end.map { |h| h.slice(:product_id, :customer_id) }





                        share|improve this answer















                        Using



                        def merge_by(a,b, key)
                        (a+b).group_by { |h| h[key] }
                        .each_value.map { |arr| arr.inject(:merge) }
                        end

                        merge_by(
                        merge_by(customer_mapping, customer_with_products, :customer_order_id),
                        product_mapping,
                        :product_order_id
                        ).select { |h| h[:product_id] }.map { |h| h.slice(:product_id, :customer_id) }

                        #=>[{:product_id=>"j", :customer_id=>"a"},
                        # {:product_id=>"k", :customer_id=>"b"},
                        # {:product_id=>"l", :customer_id=>"c"}]


                        Definitely not the cleanest solution, if your initial arrays come from SQL queries, I think those queries could be modified to aggregate your data properly.



                        merge_by(customer_mapping, customer_with_products, :customer_order_id)
                        # => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
                        # {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
                        # {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
                        # {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
                        # {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]


                        Then merge it similarly with your last array and cleanup the result selecting only the elements for which :product_id was found, slicing wanted keys.



                        Alternatively, a much more readable solution, depending on your array sizes might be slower as it keeps iterating over the hashes:



                        product_mapping.map do |hc| 
                        b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
                        a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
                        [hc, a_match, b_match].inject(:merge)
                        end.map { |h| h.slice(:product_id, :customer_id) }






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Nov 21 '18 at 18:59

























                        answered Nov 21 '18 at 18:47









                        Marcin KołodziejMarcin Kołodziej

                        4,5101315




                        4,5101315

























                            1














                            Following your handling of the problem the solution would be the following:



                            result_hash_array = product_mapping.map do |product_mapping_entry|
                            customer_receipt = customer_with_products.find do |customer_with_products_entry|
                            product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
                            end
                            customer_id = customer_mapping.find do |customer_mapping_entry|
                            customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
                            end[:customer_id]
                            {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
                            end


                            Output



                            results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
                            {:product_id=>"k", :customer_id=>"b"},
                            {:product_id=>"l", :customer_id=>"c"}]





                            share|improve this answer






























                              1














                              Following your handling of the problem the solution would be the following:



                              result_hash_array = product_mapping.map do |product_mapping_entry|
                              customer_receipt = customer_with_products.find do |customer_with_products_entry|
                              product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
                              end
                              customer_id = customer_mapping.find do |customer_mapping_entry|
                              customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
                              end[:customer_id]
                              {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
                              end


                              Output



                              results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
                              {:product_id=>"k", :customer_id=>"b"},
                              {:product_id=>"l", :customer_id=>"c"}]





                              share|improve this answer




























                                1












                                1








                                1







                                Following your handling of the problem the solution would be the following:



                                result_hash_array = product_mapping.map do |product_mapping_entry|
                                customer_receipt = customer_with_products.find do |customer_with_products_entry|
                                product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
                                end
                                customer_id = customer_mapping.find do |customer_mapping_entry|
                                customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
                                end[:customer_id]
                                {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
                                end


                                Output



                                results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
                                {:product_id=>"k", :customer_id=>"b"},
                                {:product_id=>"l", :customer_id=>"c"}]





                                share|improve this answer















                                Following your handling of the problem the solution would be the following:



                                result_hash_array = product_mapping.map do |product_mapping_entry|
                                customer_receipt = customer_with_products.find do |customer_with_products_entry|
                                product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
                                end
                                customer_id = customer_mapping.find do |customer_mapping_entry|
                                customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
                                end[:customer_id]
                                {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
                                end


                                Output



                                results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
                                {:product_id=>"k", :customer_id=>"b"},
                                {:product_id=>"l", :customer_id=>"c"}]






                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Nov 21 '18 at 19:35

























                                answered Nov 21 '18 at 19:20









                                MrCodeXMrCodeX

                                315




                                315























                                    0














                                    Other option, starting from customer_mapping, one liner (but quite wide):



                                    customer_mapping.map { |e| {customer_id: e[:customer_id], product_id: (product_mapping.detect { |k| k[:product_order_id] == (customer_with_products.detect{ |h| h[:customer_order_id] == e[:customer_order_id] } || {} )[:product_order_id] } || {} )[:product_id]  } }

                                    #=> [{:customer_id=>"a", :product_id=>"j"},
                                    # {:customer_id=>"b", :product_id=>"k"},
                                    # {:customer_id=>"c", :product_id=>"l"},
                                    # {:customer_id=>"d", :product_id=>nil},
                                    # {:customer_id=>"e", :product_id=>nil}]





                                    share|improve this answer






























                                      0














                                      Other option, starting from customer_mapping, one liner (but quite wide):



                                      customer_mapping.map { |e| {customer_id: e[:customer_id], product_id: (product_mapping.detect { |k| k[:product_order_id] == (customer_with_products.detect{ |h| h[:customer_order_id] == e[:customer_order_id] } || {} )[:product_order_id] } || {} )[:product_id]  } }

                                      #=> [{:customer_id=>"a", :product_id=>"j"},
                                      # {:customer_id=>"b", :product_id=>"k"},
                                      # {:customer_id=>"c", :product_id=>"l"},
                                      # {:customer_id=>"d", :product_id=>nil},
                                      # {:customer_id=>"e", :product_id=>nil}]





                                      share|improve this answer




























                                        0












                                        0








                                        0







                                        Other option, starting from customer_mapping, one liner (but quite wide):



                                        customer_mapping.map { |e| {customer_id: e[:customer_id], product_id: (product_mapping.detect { |k| k[:product_order_id] == (customer_with_products.detect{ |h| h[:customer_order_id] == e[:customer_order_id] } || {} )[:product_order_id] } || {} )[:product_id]  } }

                                        #=> [{:customer_id=>"a", :product_id=>"j"},
                                        # {:customer_id=>"b", :product_id=>"k"},
                                        # {:customer_id=>"c", :product_id=>"l"},
                                        # {:customer_id=>"d", :product_id=>nil},
                                        # {:customer_id=>"e", :product_id=>nil}]





                                        share|improve this answer















                                        Other option, starting from customer_mapping, one liner (but quite wide):



                                        customer_mapping.map { |e| {customer_id: e[:customer_id], product_id: (product_mapping.detect { |k| k[:product_order_id] == (customer_with_products.detect{ |h| h[:customer_order_id] == e[:customer_order_id] } || {} )[:product_order_id] } || {} )[:product_id]  } }

                                        #=> [{:customer_id=>"a", :product_id=>"j"},
                                        # {:customer_id=>"b", :product_id=>"k"},
                                        # {:customer_id=>"c", :product_id=>"l"},
                                        # {:customer_id=>"d", :product_id=>nil},
                                        # {:customer_id=>"e", :product_id=>nil}]






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Nov 22 '18 at 7:13

























                                        answered Nov 21 '18 at 19:46









                                        iGianiGian

                                        4,7842725




                                        4,7842725























                                            0














                                            cust_order_id_to_cust_id =
                                            customer_mapping.each_with_object({}) do |g,h|
                                            h[g[:customer_order_id]] = g[:customer_id]
                                            end
                                            #=> {"g1"=>"a", "g2"=>"b", "g3"=>"c", "g4"=>"d", "g5"=>"e"}

                                            prod_order_id_to_cust_order_id =
                                            customer_with_products.each_with_object({}) do |g,h|
                                            h[g[:product_order_id]] = g[:customer_order_id]
                                            end
                                            #=> {"a1"=>"g1", "a2"=>"g2", "a3"=>"g3", "a4"=>"g4", "a5"=>"g5"}

                                            product_mapping.map do |h|
                                            { product_id: h[:product_id], customer_id:
                                            cust_order_id_to_cust_id[prod_order_id_to_cust_order_id[h[:product_order_id]]] }
                                            end
                                            #=> [{:product_id=>"j", :customer_id=>"a"},
                                            # {:product_id=>"k", :customer_id=>"b"},
                                            # {:product_id=>"l", :customer_id=>"c"}]


                                            This formulation is particularly easy to test. (It's so straightforward that no debugging was needed).






                                            share|improve this answer






























                                              0














                                              cust_order_id_to_cust_id =
                                              customer_mapping.each_with_object({}) do |g,h|
                                              h[g[:customer_order_id]] = g[:customer_id]
                                              end
                                              #=> {"g1"=>"a", "g2"=>"b", "g3"=>"c", "g4"=>"d", "g5"=>"e"}

                                              prod_order_id_to_cust_order_id =
                                              customer_with_products.each_with_object({}) do |g,h|
                                              h[g[:product_order_id]] = g[:customer_order_id]
                                              end
                                              #=> {"a1"=>"g1", "a2"=>"g2", "a3"=>"g3", "a4"=>"g4", "a5"=>"g5"}

                                              product_mapping.map do |h|
                                              { product_id: h[:product_id], customer_id:
                                              cust_order_id_to_cust_id[prod_order_id_to_cust_order_id[h[:product_order_id]]] }
                                              end
                                              #=> [{:product_id=>"j", :customer_id=>"a"},
                                              # {:product_id=>"k", :customer_id=>"b"},
                                              # {:product_id=>"l", :customer_id=>"c"}]


                                              This formulation is particularly easy to test. (It's so straightforward that no debugging was needed).






                                              share|improve this answer




























                                                0












                                                0








                                                0







                                                cust_order_id_to_cust_id =
                                                customer_mapping.each_with_object({}) do |g,h|
                                                h[g[:customer_order_id]] = g[:customer_id]
                                                end
                                                #=> {"g1"=>"a", "g2"=>"b", "g3"=>"c", "g4"=>"d", "g5"=>"e"}

                                                prod_order_id_to_cust_order_id =
                                                customer_with_products.each_with_object({}) do |g,h|
                                                h[g[:product_order_id]] = g[:customer_order_id]
                                                end
                                                #=> {"a1"=>"g1", "a2"=>"g2", "a3"=>"g3", "a4"=>"g4", "a5"=>"g5"}

                                                product_mapping.map do |h|
                                                { product_id: h[:product_id], customer_id:
                                                cust_order_id_to_cust_id[prod_order_id_to_cust_order_id[h[:product_order_id]]] }
                                                end
                                                #=> [{:product_id=>"j", :customer_id=>"a"},
                                                # {:product_id=>"k", :customer_id=>"b"},
                                                # {:product_id=>"l", :customer_id=>"c"}]


                                                This formulation is particularly easy to test. (It's so straightforward that no debugging was needed).






                                                share|improve this answer















                                                cust_order_id_to_cust_id =
                                                customer_mapping.each_with_object({}) do |g,h|
                                                h[g[:customer_order_id]] = g[:customer_id]
                                                end
                                                #=> {"g1"=>"a", "g2"=>"b", "g3"=>"c", "g4"=>"d", "g5"=>"e"}

                                                prod_order_id_to_cust_order_id =
                                                customer_with_products.each_with_object({}) do |g,h|
                                                h[g[:product_order_id]] = g[:customer_order_id]
                                                end
                                                #=> {"a1"=>"g1", "a2"=>"g2", "a3"=>"g3", "a4"=>"g4", "a5"=>"g5"}

                                                product_mapping.map do |h|
                                                { product_id: h[:product_id], customer_id:
                                                cust_order_id_to_cust_id[prod_order_id_to_cust_order_id[h[:product_order_id]]] }
                                                end
                                                #=> [{:product_id=>"j", :customer_id=>"a"},
                                                # {:product_id=>"k", :customer_id=>"b"},
                                                # {:product_id=>"l", :customer_id=>"c"}]


                                                This formulation is particularly easy to test. (It's so straightforward that no debugging was needed).







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Nov 22 '18 at 8:53

























                                                answered Nov 22 '18 at 8:47









                                                Cary SwovelandCary Swoveland

                                                70.6k54167




                                                70.6k54167























                                                    0














                                                    I would recommended to rather take a longer but more readable solution which you also understand in some months from now by looking at it. Use full names for the hash keys instead of hiding them behind k, v for more complexe lookups (maybe its just my personal preference).



                                                    I would suggest somethink like:



                                                    result = product_mapping.map do |mapping|
                                                    customer_id = customer_mapping.find do |hash|
                                                    hash[:customer_order_id] == customer_with_products.find do |hash|
                                                    hash[:product_order_id] == mapping[:product_order_id]
                                                    end[:customer_order_id]
                                                    end[:customer_id]

                                                    { product_id: mapping[:product_id], customer_id: customer_id }
                                                    end





                                                    share|improve this answer




























                                                      0














                                                      I would recommended to rather take a longer but more readable solution which you also understand in some months from now by looking at it. Use full names for the hash keys instead of hiding them behind k, v for more complexe lookups (maybe its just my personal preference).



                                                      I would suggest somethink like:



                                                      result = product_mapping.map do |mapping|
                                                      customer_id = customer_mapping.find do |hash|
                                                      hash[:customer_order_id] == customer_with_products.find do |hash|
                                                      hash[:product_order_id] == mapping[:product_order_id]
                                                      end[:customer_order_id]
                                                      end[:customer_id]

                                                      { product_id: mapping[:product_id], customer_id: customer_id }
                                                      end





                                                      share|improve this answer


























                                                        0












                                                        0








                                                        0







                                                        I would recommended to rather take a longer but more readable solution which you also understand in some months from now by looking at it. Use full names for the hash keys instead of hiding them behind k, v for more complexe lookups (maybe its just my personal preference).



                                                        I would suggest somethink like:



                                                        result = product_mapping.map do |mapping|
                                                        customer_id = customer_mapping.find do |hash|
                                                        hash[:customer_order_id] == customer_with_products.find do |hash|
                                                        hash[:product_order_id] == mapping[:product_order_id]
                                                        end[:customer_order_id]
                                                        end[:customer_id]

                                                        { product_id: mapping[:product_id], customer_id: customer_id }
                                                        end





                                                        share|improve this answer













                                                        I would recommended to rather take a longer but more readable solution which you also understand in some months from now by looking at it. Use full names for the hash keys instead of hiding them behind k, v for more complexe lookups (maybe its just my personal preference).



                                                        I would suggest somethink like:



                                                        result = product_mapping.map do |mapping|
                                                        customer_id = customer_mapping.find do |hash|
                                                        hash[:customer_order_id] == customer_with_products.find do |hash|
                                                        hash[:product_order_id] == mapping[:product_order_id]
                                                        end[:customer_order_id]
                                                        end[:customer_id]

                                                        { product_id: mapping[:product_id], customer_id: customer_id }
                                                        end






                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Nov 22 '18 at 11:49









                                                        SG 86SG 86

                                                        4,99711829




                                                        4,99711829






























                                                            draft saved

                                                            draft discarded




















































                                                            Thanks for contributing an answer to Stack Overflow!


                                                            • Please be sure to answer the question. Provide details and share your research!

                                                            But avoid



                                                            • Asking for help, clarification, or responding to other answers.

                                                            • Making statements based on opinion; back them up with references or personal experience.


                                                            To learn more, see our tips on writing great answers.




                                                            draft saved


                                                            draft discarded














                                                            StackExchange.ready(
                                                            function () {
                                                            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53418008%2fbuild-a-new-array-of-hash-from-multiple-array-of-hashes%23new-answer', 'question_page');
                                                            }
                                                            );

                                                            Post as a guest















                                                            Required, but never shown





















































                                                            Required, but never shown














                                                            Required, but never shown












                                                            Required, but never shown







                                                            Required, but never shown

































                                                            Required, but never shown














                                                            Required, but never shown












                                                            Required, but never shown







                                                            Required, but never shown







                                                            Popular posts from this blog

                                                            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                                                            ComboBox Display Member on multiple fields

                                                            Is it possible to collect Nectar points via Trainline?