1

I am trying to convert one of my array into some format where it can convert itself into table format.

I have an array which is:

  [
    {
    id: 1,
    Revenue_Account: "Revenue Receipt",
    Amount: 59567,
    Year: "2012-13",
    created_at: "2018-08-21T06:30:17.000Z",
    updated_at: "2018-08-21T06:30:17.000Z"
    },
    {
    id: 2,
    Revenue_Account: "Revenue Expenditure ",
    Amount: 54466,
    Year: "2012-13",
    created_at: "2018-08-21T06:30:17.000Z",
    updated_at: "2018-08-21T06:30:17.000Z"
    },

    ...

]

Full code of my array link to my actual array

I want this data to be converted into this format:

data: [
        {
        id: 1,
        Sector: "Revenue Receipt",
        2012-13: 59567,
        2013-14: 68919,
        2014-15: 72570,
        2015-16: 96123,
        2016-17: 105585,
        2017-18_BE: 137158,
        },
        {
        id: 2,
        Sector: "Revenue Expenditure",
        2012-13: 59567,
        2013-14: 68919,
        2014-15: 72570,
        2015-16: 96123,
        2016-17: 105585,
        2017-18_BE: 137158,
        },
  ....
]

I am using this code to group my array:

 group = b.group_by{|data| data[:Revenue_Account]}

this is grouping my data as I am expecting in order to achieve my goal I am trying this code.

  group = b.group_by{|data| data[:Revenue_Account]}
  du = []
  group.each do |i|
  du.push({Sector:i[0]})
  end

This is giving me Sector wise result how can I add year in my code.

Coding
  • 21
  • 5

2 Answers2

2

You can't have a single id in there because you're grouping up many entries with different ids, but this is how you'd get the array in the format you're asking for:

grouped = {}
b.each do |x|
  grouped[x[:Revenue_Account]] ||= {}
  grouped[x[:Revenue_Account]][:Sector] = x[:Revenue_Account]
  grouped[x[:Revenue_Account]][x[:Year]] = x[:Amount]
end

return {data: grouped.values}

Which gets you:

{
  :data=>[
    {
      :Sector=>"Revenue Receipt",
      "2012-13"=>59567,
      "2013-14"=>68919,
      "2014-15"=>78417,
      "2015-16"=>96123,
      "2016-17"=>105585,
      "2017-18_BE"=>137158
    },  
    {
      :Sector=>"Revenue Expenditure ",
      "2012-13"=>54466,
      "2013-14"=>62477,
      "2014-15"=>72570,
      "2015-16"=>83616,
      "2016-17"=>94765,
      "2017-18_BE"=>122603
    },
  ]
}

We build a new hash by looping through the original hash and creating hash keys if they don't exist. Then we start assigning values as you want them to be in the output. On each iteration, we're creating a new key in this hash for the Revenue_Account value if its the first time we've seen it. Then we assign that particular Revenue_Account's Date and Amount to the output. So for value 'Revenue Receipt' it looks like this:

  • Grouped hash starts off as empty
  • On first iteration, we see that group["Revenue Receipt"] is nil, so we initialize it with an empty hash via ||= (assign if nil)
  • We then assign :Sector => "Revenue Receipt" and this entry's Year and Amount, "2012-13" => 59567
  • Our grouped hash looks like: {"Revenue Receipt" => {:Sector => "Revenue Receipt", "2012-13" => 59567}
  • On the next iteration we see that group["Revenue Receipt"] is not nil, so ||= does not override it with an empty hash
  • We then assign :Sector => "Revenue Receipt" and this entry's Year and Amount, "2012-14" => 68919, which adds a new key/value to the existing hash
  • Our grouped hash now looks like: {"Revenue Receipt" => {:Sector => "Revenue Receipt", "2012-13" => 59567, "2012-14" => 68919}
  • After we parse the entire array, we now have a hash that has a key of the Revenue_Account, and values which look like the hash output you're expecting.
  • We discard the key and return only the hash values, which gets you the final output.
Billy Kimble
  • 798
  • 3
  • 9
1

Another option, directly manipulating the array.

array_of_data = array
.each { |h| h[:Sector] = h.delete(:Revenue_Account) }
.each { |h| h[h[:Year]] = h[:Amount]}
.each { |h| h.delete_if{ |k, _| k == :created_at || k == :updated_at || k == :id || k == :Year || k == :Amount} }
.group_by { |h| h[:Sector] }
.values.map { |a| a.inject(:merge) }

Then just:

h = {}
h[:data] = array_of_data

To understand what happens along the code, just ad line by line outputting the result, like:

p array
    .each { |h| h[:Sector] = h.delete(:Revenue_Account) }

Then:

p array
    .each { |h| h[:Sector] = h.delete(:Revenue_Account) }
    .each { |h| h[h[:Year]] = h[:Amount]}

Etcetera...

To understand .inject(:merge), see here Rails mapping array of hashes onto single hash

iGian
  • 11,023
  • 3
  • 21
  • 36