Jan
Jan

Reputation: 16094

how to merge Hashes in Ruby/Rails

I have a Hash like this, which should be "merged" to its uniq nested values

[
  {
    "slug": "color",
    "values": [{ "slug": "amethyst" },
               { "slug": "coral" }],
  },
  {
    "slug": "color",
    "values": [{ "slug": "amethyst" }],
  },
  {
    "slug": "power-source",
    "values": [{ "slug": "110V"}],
  }
]

at the same time it should count the duplicate values but made uniq in an items array:

 {  "slug": "color",
    "items": [
             {
              "slug": "amethyst",
              "count": 2
             },
             {
              "slug": "coral",
              "count": 1
             }]
 },
{
   "slug": "power-source",
   "items": [
             {
              "slug": "110V",
              "count": 1
             }]
 }
]

is there a "Rails method" to achieve this?

Thank you

Upvotes: 0

Views: 74

Answers (1)

Sebastián Palma
Sebastián Palma

Reputation: 33420

I think there's nothing built-in in Rails that allows you to get such a custom requirement, but you can achieve it by playing around with different methods and their return values:

data
  .group_by { |hash| hash[:slug] }
  .transform_values do |values|
    values
      .flat_map { |vals| vals[:values] }
      .group_by { |value| value[:slug] }
      .transform_values(&:count)
  end.map do |slug, items|
    [slug, items.map { |item, count| {slug: item, count: count} }]
  end.map { |slug, items| {slug: slug, items: items} }
  # [{:slug=>"color",
  #   :items=>[{:slug=>"amethyst", :count=>2}, {:slug=>"coral", :count=>1}]},
  #  {:slug=>"power-source", :items=>[{:slug=>"110V", :count=>1}]}]

As you see, you can first group every hash in the array by their slug value, then transform the values that hash contains, mapping and flattening every array by their values key and then grouping to get their total.

After that you can just create the hash with its keys/values you need.

It might simplify the things a bit if you end up with a single hash, whose keys are the "slugs" and contains the items as its values.

Upvotes: 2

Related Questions