Home > Software engineering >  How to group an array of hash by its value which has key-value pair in Ruby (Rails)?
How to group an array of hash by its value which has key-value pair in Ruby (Rails)?

Time:01-01

So I have following array of hash:

my_array = [
  {
    "date" => "2022-12-01",
    "pic" => "Jason",
    "guard" => "Steven",
    "front_desk" => "Emily"
  },
  {
    "date" => "2022-12-02",
    "pic" => "Gilbert",
    "guard" => "Johnny",
    "front_desk" => "Bella"
  },
  {
    "date" => "2022-12-03",
    "pic" => "Steven",
    "guard" => "Gilbert",
    "front_desk" => "Esmeralda"
  }
]

My question is how do I change the structure of my array (grouping) by date in Ruby (Rails 7). Or in other word, I want to change my array into something like this:

my_array = [
  {
    "2022-12-01" => {
        "pic" => "Jason",
        "guard" => "Steven",
        "front_desk" => "Emily"
    {
  },
  {
    "2022-12-02" => {
      "pic" => "Gilbert",
      "guard" => "Johnny",
      "front_desk" => "Bella"
    }
  },
  {
    "2022-12-03" => {
      "pic" => "Steven",
      "guard" => "Gilbert",
      "front_desk" => "Esmeralda"
    }
  }
]

Anyway, thanks in advance for the answer

I have tried using group_by method to group by its date, but it doesn't give the output I wanted

I've tried this method:

my_array.group_by { |element| element["date"] }.values

CodePudding user response:

If you simply want a 1:1 mapping of your input objects to an output object of a new shape, then you just need to use Array#map:

my_array.map {|entry| {entry["date"] => entry.except("date")} }

(Hash#except comes from ActiveSupport, and is not standard Ruby, but since you're in Rails it should work just fine).

CodePudding user response:

Both solutions assume the key "date" will be unique. If we cannot make this assumption safely, then each date should be mapped to an array of hashes.

my_array.each_with_object({}) do |x, hsh|
  date = x["date"]
  hsh[date] ||= []
  hsh[date] << x.except("date")
end

Result:

{
  "2022-12-01" => [
    {"pic"=>"Jason", "guard"=>"Steven", "front_desk"=>"Emily"}
  ], 
  "2022-12-02" => [
    {"pic"=>"Gilbert", "guard"=>"Johnny", "front_desk"=>"Bella"}
  ], 
  "2022-12-03" => [
    {"pic"=>"Steven", "guard"=>"Gilbert", "front_desk"=>"Esmeralda"}
  ]
}

Or you may like:

my_array
  .sort_by { |x| x["date"] }
  .group_by { |x| x["date"] }
  .transform_values { |x| x.except("date") }

CodePudding user response:

Try this

result = my_array.each_with_object({}) do |element, hash|
 hash[element["date"]] = element.except("date")
end

puts result 

I hope this helps! :)

  • Related