I have some JSON data that stores a date time string and total. e.g.
[{
"Date": "2012-04-01 12:00:00",
"Total": "14"
}, {
"Date": "2012-04-02 06:00:00",
"Total": "3"
}, {
"Date": "2012-04-02 14:00:00",
"Total": "12"
}, {
"Date": "2012-04-02 16:00:00",
"Total": "5"
}, {
"Date": "2012-04-02 17:00:00",
"Total": "7"
}, {
"Date": "2012-04-03 06:00:00",
"Total": "9"
}, {
"Date": "2012-04-03 14:00:00",
"Total": "2"
}, {
"Date": "2012-04-04 06:00:00",
"Total": "1"
}, {
"Date": "2012-04-04 14:00:00",
"Total": "10"
}, {
"Date": "2012-04-04 19:00:00",
"Total": "8"
}, {
"Date": "2012-04-04 21:00:00",
"Total": "4"
}]
What I'd like to do is create new JSON objects for data that is the same year, month, and day.
So for example a full set of data could be formatted into:
DAY:
[{
"Date": "2012-04-01"
"Total": "3"
},{
"Date": "2012-04-02"
"Total": "4"
},{
"Date": "2012-04-03"
"Total": "6"
}]
MONTH:
[{
"Date": "2012-04"
"Total": "36"
},{
"Date": "2012-05"
"Total": "11"
},{
"Date": "2012-06"
"Total": "23"
},{
"Date": "2012-07"
"Total": "17"
}]
YEAR:
[{
"Date": "2012"
"Total": "91"
},{
"Date": "2013"
"Total": "102"
},{
"Date": "2014"
"Total": "78"
}]
How could I do this is Rails? If I could get an example of how I could do one of them, then I could then use that as a base to do the others!
So in the controller I have:
def get_count_day
render json: data.to_json
end
def get_count_month
render json: data.to_json
end
def get_count_year
render json: data.to_json
end
count_by_day =
json.group_by{ |record| record[:Date].to_date.strftime }
.map { |k, v| { Date: k, Total: v.map { |y| y[:Total].to_i }.sum.to_s } }
#=> [{:Date=>"2012-04-01", :Total=>"14"}, {:Date=>"2012-04-02", :Total=>"27"}, {:Date=>"2012-04-03", :Total=>"11"}, {:Date=>"2012-04-04", :Total=>"23"}]
count_by_month =
json.group_by{ |record| record[:Date].to_date.strftime('%Y-%m') }
.map { |k, v| { Date: k, Total: v.map { |y| y[:Total].to_i }.sum.to_s } }
#=> [{:Date=>"2012-04", :Total=>"75"}]
count_by_year =
json.group_by{ |record| record[:Date].to_date.strftime('%Y') }
.map { |k, v| { Date: k, Total: v.map { |y| y[:Total].to_i }.sum.to_s } }
#=> [{:Date=>"2012", :Total=>"75"}]
Hey you can try this way for Day
given_json.group_by{|b| b["Date"].to_date.strftime("%Y-%d-%m")}.collect{|key,value| {"Date" =>key , "Total" => value.sum{|d| d["Total"].to_i}}}
For Month
given_json.group_by{|b| b["Date"].to_date.strftime("%Y-%m")}.collect{|key,value| {"Date" =>key , "Total" => value.sum{|d| d["Total"].to_i}}}
For Year
given_json.group_by{|b| b["Date"].to_date.strftime("%Y")}.collect{|key,value| {"Date" =>key , "Total" => value.sum{|d| d["Total"].to_i}}}
Here is an example to retrieve them grouped by day:
grouped_json = Hash.new(0)
your_json_array.each do |array_element|
date = Date.parse(array_element['Date']).strftime('%Y-%m-%d')
grouped_json[date] += array_element['Total']
end
grouped_json.map {|k,v| {'Date' => k, 'Total' => v} }
by month?
grouped_json = Hash.new(0)
your_json_array.each do |array_element|
date = Date.parse(array_element['Date']).strftime('%Y-%m')
grouped_json[date] += array_element['Total']
end
grouped_json.map {|k,v| {'Date' => k, 'Total' => v} }
by year?
grouped_json = Hash.new(0)
your_json_array.each do |array_element|
date = Date.parse(array_element['Date']).strftime('%Y')
grouped_json[date] += array_element['Total']
end
grouped_json.map {|k,v| {'Date' => k, 'Total' => v} }
Related
I have the following data structure:
a = [
{ "payer": "UNILEVER", "points": 200, "timestamp": "2020-10-31T11:00:00Z" },
{ "payer": "DANNON", "points": -200, "timestamp": "2020-10-31T15:00:00Z" },
{ "payer": "MILLER COORS", "points": 10000, "timestamp": "2020-11-01T14:00:00Z" },
{ "payer": "DANNON", "points": 300, "timestamp": "2020-10-31T10:00:00Z" }
]
I want to sum up all point by payer. How can I do so?
a.group_by { |element| element[:payer] }.each_with_object({}) { |(payer, records), result| result[payer] = records.inject(0) { |sum, record| sum + record[:points] } }
=> {"UNILEVER"=>200, "DANNON"=>100, "MILLER COORS"=>10000}
a.group_by {|h| h[:payer] }
.transform_values {|a| a.sum {|h| h[:points] } }
# => {"UNILEVER"=>200, "DANNON"=>100, "MILLER COORS"=>10000}
Input
a = [{ "payer": "UNILEVER", "points": 200, "timestamp": "2020-10-31T11:00:00Z" },
{ "payer": "DANNON", "points": -200, "timestamp": "2020-10-31T15:00:00Z" },
{ "payer": "MILLER COORS", "points": 10000, "timestamp": "2020-11-01T14:00:00Z" },
{ "payer": "DANNON", "points": 300, "timestamp": "2020-10-31T10:00:00Z" }]
Code
result=a.group_by { |h| h[:payer] }.values.map do |arr|
arr.reduce do |h1, h2|
h1.merge(h2) do |k, f, s|
k.eql?(:points) ? f + s : f
end
end
end
p result
Output
#=>[{:payer=>"UNILEVER", :points=>200, :timestamp=>"2020-10-31T11:00:00Z"}, {:payer=>"DANNON", :points=>100, :timestamp=>"2020-10-31T15:00:00Z"}, {:payer=>"MILLER COORS", :points=>10000, :timestamp=>"2020-11-01T14:00:00Z"}]
You can get result with single loop:
a.each_with_object(Hash.new { |h, k| h[k] = 0 }) { |o, r| r[o[:payer]] += o[:points] }
# => {"UNILEVER"=>200, "DANNON"=>100, "MILLER COORS"=>10000}
I have the following OData V4 query:
.../odata/Locations/?$select=Id&$filter=(Id eq 9bb29421-5160-4546-b87f-a78c0074f5c5 or Id eq 8b2a9727-a642-446e-b992-76c6d1584989)&$expand=Assets($select=Id;$filter=ParentAssetId eq null;$expand=Jobs($select=Id;$count=true;$top=0))
with the following, as expected, result:
{
"#odata.context": ".../odata/$metadata#Locations(Id,Assets(Id,Jobs(Id)))",
"value": [
{
"Id": "8b2a9727-a642-446e-b992-76c6d1584989",
"Assets": [
{
"Id": "540d0855-aa1c-4e94-9d0b-332c99ec00b6",
"Jobs#odata.count": 2,
"Jobs": []
},
{
"Id": "6dcaa0e8-fc31-4d86-9f1a-a64300f8815c",
"Jobs#odata.count": 1,
"Jobs": []
},
{
"Id": "db4cf86b-9f42-4a99-b7b4-a64300f8c740",
"Jobs#odata.count": 1,
"Jobs": []
}
]
},
{
"Id": "9bb29421-5160-4546-b87f-a78c0074f5c5",
"Assets": [
{
"Id": "08a2a046-86c1-41a9-b2b1-a7ac007bed64",
"Jobs#odata.count": 1,
"Jobs": []
},
{
"Id": "2b76dad1-4058-4261-8a40-a7af00cb8bd5",
"Jobs#odata.count": 1,
"Jobs": []
},
{
"Id": "3a5472a1-68c4-4dc4-b2cd-a797007b0068",
"Jobs#odata.count": 2,
"Jobs": []
}
]
}
]
}
How can I sum the Jobs#odata.count values and return a single value: 8?
I have tried some &$apply=aggregate(Assets/Jobs#odata.count with sum as Total) but it is an incorrect syntax :(
I fixed this by changing the query perspective and count the Jobs from the beginning:
.../odata/Jobs/$count/?$expand=Asset($select=LocationId)&$filter=Asset/LocationId in (9bb29421-5160-4546-b87f-a78c0074f5c5, 8b2a9727-a642-446e-b992-76c6d1584989)
I am trying to load data from redis db. I have a api only rails app and trying to render the json data as per requirement.
Currently I am able to get the data from redis in the following format.
[
{
"id": 1,
"name": "Stephenie Meyer",
"created_at": "2018-04-17T07:40:50.417Z",
"updated_at": "2018-04-17T07:40:50.417Z"
},
{
"id": 2,
"name": "V.C. Andrews",
"created_at": "2018-04-17T07:40:50.613Z",
"updated_at": "2018-04-17T07:40:50.613Z"
},
{
"id": 3,
"name": "Sophie Kinsella",
"created_at": "2018-04-17T07:40:50.646Z",
"updated_at": "2018-04-17T07:40:50.646Z"
}
]
How can convert this in a way such that the key value pairs of name,created and updated will be hash to a id key-value pair.
Into this
{"id": 1,
{
"name": "Stephenie Meyer",
"created_at": "2018-04-17T07:40:50.417Z",
"updated_at": "2018-04-17T07:40:50.417Z"
}
}
helper method for getting redis data.
def fetch_authors
authors = $redis.get('authors')
if authors.nil?
authors = Author.all.to_json
$redis.set("authors", authors).to_json
$redis.expire("authors", 5.hour.to_i)
end
JSON.load authors
end
And displaying on index page using
def index
#authors = fetch_authors
render json: #authors
end
The closest to what you want would probably be:
input = ...
input.map { |hash| [hash.delete(:id) || hash.delete('id'), hash] }.to_h
#⇒ {{1=>{:name=>...},
# {2=>{:name=>...},
# {3=>{:name=>...}}
Not exactly what you want because that's not correct syntax but you can achieve something similar with group_by
arr = [
{
"id": 1,
"name": "Stephenie Meyer",
"created_at": "2018-04-17T07:40:50.417Z",
"updated_at": "2018-04-17T07:40:50.417Z"
},
{
"id": 2,
"name": "V.C. Andrews",
"created_at": "2018-04-17T07:40:50.613Z",
"updated_at": "2018-04-17T07:40:50.613Z"
},
{
"id": 3,
"name": "Sophie Kinsella",
"created_at": "2018-04-17T07:40:50.646Z",
"updated_at": "2018-04-17T07:40:50.646Z"
}
]
arr.group_by { |e| e[:id] }
This will return
{
1 => [
{
:id => 1,
:name => "Stephenie Meyer",
:created_at => "2018-04-17T07:40:50.417Z",
:updated_at => "2018-04-17T07:40:50.417Z"
}
],
2 => [
{
:id => 2,
:name => "V.C. Andrews",
:created_at => "2018-04-17T07:40:50.613Z",
:updated_at => "2018-04-17T07:40:50.613Z"
}
],
3 => [
{
:id => 3,
:name => "Sophie Kinsella",
:created_at => "2018-04-17T07:40:50.646Z",
:updated_at => "2018-04-17T07:40:50.646Z"
}
]
}
Hi guys I am having trouble to find out a solution to a problem.So I have an array like bellow.
{
"9": [
{
"id": "9",
"day": "2017-08-02",
"voltage": "3397.1"
},
{
"id": "9",
"day": "2017-08-01",
"voltage": "11518.67"
},
{
"id": "9",
"day": "2017-07-31",
"voltage": "12835.5900000002"
}
],
"11": [
{
"id": "11",
"day": "2017-08-02",
"voltage": "910.21"
},
{
"id": "11",
"day": "2017-08-01",
"voltage": "3616.43"
},
{
"id": "11",
"day": "2017-07-31",
"voltage": "2085.37"
}
],
"12": [
{
"id": "12",
"day": "2017-08-02",
"voltage": "4793.96"
},
{
"id": "12",
"day": "2017-08-01",
"voltage": "17762.2999999998"
},
{
"id": "12",
"day": "2017-07-31",
"voltage": "18334.4000000001"
}
]
}
Now what I want to do is to produce an array like below
{
"9": [
"day": ["2017-08-02", "2017-08-01", "2017-07-31"],
"voltage": ["3397.1", "11518.67", "12835.5900000002"]
],
"11": [
"day": ["2017-08-02","2017-08-01", "2017-07-31"]
"voltage": ["910.21", "3616.43", "2085.37"]
]
...
}
and so on.
I have tried to iterate over the array using .each and .map method but it didn't work.I search trough existing solutions in stackoverflow but nothing helps me out.
Can some one help me with this.
Thanks so much in advance.
If you define hash as the original object you can do it with reduce like so:
result = hash.reduce({}) do |memo, (key, vals)|
memo[key] = {
"day" => vals.map { |val| val[:day] },
"voltage" => vals.map { |val| val[:voltage] }
}
memo
end
You can also do it with just each:
result = {}
hash.each do |key, vals|
result[key] = {
"day" => vals.map { |val| val[:day] },
"voltage" => vals.map { |val| val[:voltage] }
}
end
I am unsure if you are writing your hash as JSON or Ruby, but I didn't have time to rewrite it to Ruby, to I just copy pasted it into a script, which made all the keys be symbols.
I believe this should be working:
new_hash = {}
current_hash.each do |key, value_array|
new_hash[key] ||= {}
value_array.each do |values|
new_values = values.dup
new_values.delete(:id)
new_values.each do |attribute_name, attribute_value|
new_hash[key][attribute_name] ||= []
new_hash[key][attribute_name] << attribute_value
end
end
end
Which gives me this result:
{:"9"=>{:day=>["2017-08-02", "2017-08-01", "2017-07-31"], :voltage=>["3397.1", "11518.67", "12835.5900000002"]}, :"11"=>{:day=>["2017-08-02", "2017-08-01", "2017-07-31"], :voltage=>["910.21", "3616.43", "2085.37"]}, :"12"=>{:day=>["2017-08-02", "2017-08-01", "2017-07-31"], :voltage=>["4793.96", "17762.2999999998", "18334.4000000001"]}}
One more solution from me :)
For Ruby 2.4.0:
hash.transform_values do |values|
values.each_with_object({}) do |value, memo|
memo[:day] ? memo[:day] << value[:day] : memo[:day] = [value[:day]]
memo[:voltage] ? memo[:voltage] << value[:voltage] : memo[:voltage] = [value[:voltage]]
end
end
And for earlier:
hash.map do |key, values|
[
key,
values.each_with_object({}) do |value, memo|
memo[:day] ? memo[:day] << value[:day] : memo[:day] = [value[:day]]
memo[:voltage] ? memo[:voltage] << value[:voltage] : memo[:voltage] = [value[:voltage]]
end
]
end.to_h
I am grabbing value data: name, uid, highschool_name, graduateschool_name like this:
def add_friends
facebook.get_connections("me", "friends", :fields => "name, id, education").each do |hash|
self.friends.where(:name => hash['name'],
:uid => hash['id'],
:highschool_name => hash['education']['school']['name'] unless hash["education"].blank?,
:graduateschool_name => hash['education']['school']['name'] unless hash["education"].blank?).
first_or_create
end
end
From an array of hash:
"education": [
{
"school": {
"id": "110703012290674",
"name": "Kunskapsgymnasiet Malmö"
},
"year": {
"id": "136328419721520",
"name": "2009"
},
"type": "High School"
},
{
"school": {
"id": "112812485399398",
"name": "Malmö University"
},
"year": {
"id": "118118634930920",
"name": "2012"
},
"concentration": [
{
"id": "104076956295773",
"name": "Computer Science"
}
],
"type": "Graduate School",
"classes": [
{
"id": "165093923542525",
"name": "Programmering",
"description": "Kursen fokuserar på metoder och tekniker vid utveckling av webbapplikationer med hjälp av HTML5."
}
]
}
],
EDIT:
This code dosent work. I would like to pick every hichschool and Graduate School from this array of hash and save it.
high_schools = response['education'].collect{|ed| ed['school']['name'] if ed['type'] == "High School" }
grad_schools = response['education'].collect{|ed| ed['school']['name'] if ed['type'] == "Graduate School" }