0

Hey I have an array of hash values as follows.

[{"group" => "1", "message" => "hey", "weight" => 1}, {"group" => "1", "message" 
 => "hey1", "weight" => 2}, {"group" => "2", "message" => "hey3", "weight" => 4}]

I want to group_by group and format it so that I get the following:

[{"group" => 1, "messages" => {"hey","hey1"}, "weights" => {1,2}}, {"group" => 2,
  "messages" => {"hey3"}, "weights" => {4}}]

Is there a nice ruby way to achieve this?

Edit: Now I have:

[
  {"group" => "1", "message" => {"hey" => "1"}},
  {"group" => "1", "message" => {"hey1" => "2"}}
]

I'd like to have

{"group" => "1", "messages" => {"hey1" => "1", "hey2" => "2"} }
5
  • 3
    You mean [{"group" => 1, "messages" => ["hey","hey1"], "weights" => [1,2]}? Commented Jun 20, 2012 at 19:45
  • You mean arrays of the messages and weights, right, assuming that they're both ordered the same? Personally, I'd just key off the group, and keep the message and weight as a complete object to avoid any confusion. Commented Jun 20, 2012 at 19:46
  • 1
    Duplicate of Merge array of hashes to get hash of arrays of values Commented Jun 20, 2012 at 19:57
  • Yeah I kept msg and weight as own object so now I have the following [{"group" => "1", "message" => {"hey" => "1"}}, {"group" => "1", "message" => {"hey1" => "2"}}] I'd like to have [{"group" => "1", "messages" => {"hey1" => "1", "hey2" => 2"}] Commented Jun 20, 2012 at 19:58
  • Your needs are rather underspecified. What do you want for [{a:1},{a:2}] or [{a:1},{b:2}] or [{a:{b:3}},{a:{b:3}}] or [{a:{b:3}},{a:{b:4}}]? Commented Jun 20, 2012 at 20:20

2 Answers 2

2

Based on your revised question:

groups = [
  {"group" => "1", "message" => {"hey" => "1"}},
  {"group" => "1", "message" => {"hey1" => "2"}}
]

merged = groups.inject do |h1,h2|
  h1.merge(h2) do |k,v1,v2|
    if v1==v2
      v1
    elsif v1.is_a?(Hash) && v2.is_a?(Hash)
      v1.merge(v2)
    else
      [*v1,*v2]
    end
  end
end

p merged
#=> {"group"=>"1", "message"=>{"hey"=>"1", "hey1"=>"2"}}
Sign up to request clarification or add additional context in comments.

Comments

1

I think the output you want is:

[{"messages"=>["hey", "hey1"], "weights"=>[1, 2], "group"=>"1"}, {"messages"=>["hey3"], "weights"=>[4], "group"=>"2"}]

If this is the case, this code does what you want:

h.group_by { |item| item["group"] }.values.map do |item|
    item.inject({"messages" => [], "weights" => []}) do |result, subitem|
        result["group"] = subitem["group"]
        result["messages"] << subitem["message"]
        result["weights"] << subitem["weight"]
        result
    end
end

You should be able to improve it knowing more about your specific problem, but it should be a good starting point.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.