Ruby 在JSON中显示每个日期的所有值
我有以下JSON:Ruby 在JSON中显示每个日期的所有值,ruby,json,haml,Ruby,Json,Haml,我有以下JSON: { "groups" : [ { "values": "21", "date": "2013-02-22" }, { "values": "25", "date": "2013-02-22" }, { "values": "20", "date": "2013-02-22" }, {
{
"groups" : [
{
"values": "21",
"date": "2013-02-22"
},
{
"values": "25",
"date": "2013-02-22"
},
{
"values": "20",
"date": "2013-02-22"
},
{
"values": "19",
"date": "2013-02-22"
},
{
"values": "42",
"date": "2013-02-10"
},
{
"values": "30",
"date": "2013-02-10"
},
{
"values": "11",
"date": "2013-02-10"
}
]
}
我已经在Ruby类中提取了值和日期。我想找到每个日期的“最高”和“最低”值。我该怎么做
此外,我还想为相同的对象创建并行阵列。例如:
low = [12, 22, 11, 45]
high = [34, 50, 15, 60]
dates = ["2013-02-22", "2013-02-10", "2013-02-06", "2013-02-01"]
我还想显示每个日期的所有值
有人能给我一些指导吗?如果
str
是您的JSON字符串:
require 'json'
arr = JSON.parse(str)["groups"]
#=> [{"values"=>"21", "date"=>"2013-02-22"},
# {"values"=>"25", "date"=>"2013-02-22"},
# {"values"=>"20", "date"=>"2013-02-22"},
# {"values"=>"19", "date"=>"2013-02-22"},
# {"values"=>"42", "date"=>"2013-02-10"},
# {"values"=>"30", "date"=>"2013-02-10"},
# {"values"=>"11", "date"=>"2013-02-10"}]
by_date = arr.each_with_object(Hash.new {|h,k| h[k] = []}) { |g,h|
h[g["date"]] << g["values"].to_i }
# => {"2013-02-22"=>[21, 25, 20, 19], "2013-02-10"=>[42, 30, 11]}
dates = by_date.keys
#=> ["2013-02-22", "2013-02-10"]
min_vals, max_vals = *by_date.map { |_,vals| vals.minmax }
#=> [[19, 25], [11, 42]]
min_vals
#=> [19, 25]
max_vals
#=> [11, 42]
什么是“默认值”?这意味着如果散列h
没有键k
,h[k]
返回一个空数组。让我们看看这是怎么回事
最初,h#=>{}
和每个带有_对象的
设置第一个块变量,g
等于arr
的第一个值:
g = {"values"=>"21", "date"=>"2013-02-22"}
并执行块计算:
h[g["date"]] << g["values"].to_i
#=> h["2013-02-22"] << 21
然后
而h
如上所述。那么现在区块计算是:
h[g["date"]] << g["values"].to_i
#=> h["2013-02-22"] << 25
#=> [21, 25]
h #=> {"2013-02-22"=>[21, 25]}
我们看到:
by_date.map { |date, vals| vals.minmax }
#=> [[19, 25], [11, 42]]
如果*by_date.map{| date,vals | vals.minmax}
位于等式的右侧,则splat会使用并行赋值将[[19,25],[11,42]
的两个元素赋值给等式左侧的变量。每一个红宝石的诡计中都需要有诡异和奇妙的东西
由于我没有在块计算中使用date
,因此我通过将date
替换为局部变量\uu
来引起注意
编辑:回答您在评论中发布的问题,如果:
id = [1,1,1,2,2,3,4]
high = [100,100,100,90,90,100,100]
low = [20,20,20,10,10,30,40]
我正确理解你的问题,你可以先计算:
indices = id.each_with_index.to_a.uniq(&:first).map(&:last)
#=> [0, 3, 5, 6]
那么您需要的三个阵列是:
id.values_at(*indices)
#=> [1, 2, 3, 4]
high.values_at(*indices)
#=> [100, 90, 100, 100]
low.values_at(*indices)
#=> [20, 10, 30, 40]
您可以:date
并遍历日期。然后在组中创建一个:值的数组
然后使用获取正确的值和最终数组,以获取数组并分配给日期,低和高
json = {
"groups": [
{ "values": "21", "date": "2013-02-22" },
{ "values": "25", "date": "2013-02-22" },
{ "values": "20", "date": "2013-02-22" },
{ "values": "19", "date": "2013-02-22" },
{ "values": "42", "date": "2013-02-10" },
{ "values": "30", "date": "2013-02-10" },
{ "values": "11", "date": "2013-02-10" }
]
}
dates, low, high = json[:groups].group_by { |g| g[:date] }.map do |date, grouped|
values = grouped.map { |group| group[:values] }
[date, *values.minmax]
end.transpose
# => => [["2013-02-22", "2013-02-10"], ["19", "11"], ["25", "42"]]
dates
# => ["2013-02-22", "2013-02-10"]
low
# => ["19", "11"]
high
# => ["25", "42"]
你试过什么?这里的函数非常有用。欢迎使用堆栈溢出。为我们提供最少的输入数据、预期的输出以及重现您所看到的问题所需的最少代码非常重要。最后一部分,重现问题所需的最少代码帮助我们不要尝试所有可能的方法,而是关注如何解决问题。照目前情况看,您似乎还没有尝试过,也没有希望我们为您尝试,或者解释如何去做,这两种方法都不适用。当您在一个问题中给出一个示例时(通常是一件非常好的事情),重要的是输入是有效的Ruby对象。正如您所知,JSON对象是字符串,因此您需要添加单引号'{…}'
,或者使用%s[…]
或一个heredoc。此外,您应该将所有输入值分配给变量,以便在答案和注释中引用它们,而无需定义它们。例如,str=
'{…}`。非常好。做得好。这正是我要发布的内容<代码>按日期。映射{k,v{[k,v.minmax]}。to_h
也很有用。Cary,谢谢你的回答。这真的很有帮助。如果我已经在json中有了高/低值,并且能够用它创建一个数组,该怎么办?比如说,我有,high=[100100100,90,90100100]low=[20,20,20,10,10,30,40]
。我还有一组元素的标识符<代码>id=[1,1,1,2,2,3,4]。如何根据标识符拆分此文件?我希望结果是high=[10090100100]low=[20,10,30,40]id=[1,2,3,4]
。您必须更具体一些。也许最好再发一个问题。卡里,我已经把上面的评论编辑得更具体了。你明白我的问题吗?我刚看到你的评论,但我必须离开。我今天晚些时候再谈。@CarySwoveland我明白这一点,但我相信一门语言的新手必须经常阅读文档,并尝试所有的方法来回答问题,看看会发生什么,并从中学习。
by_date.map { |date, vals| vals.minmax }
#=> [[19, 25], [11, 42]]
id = [1,1,1,2,2,3,4]
high = [100,100,100,90,90,100,100]
low = [20,20,20,10,10,30,40]
indices = id.each_with_index.to_a.uniq(&:first).map(&:last)
#=> [0, 3, 5, 6]
id.values_at(*indices)
#=> [1, 2, 3, 4]
high.values_at(*indices)
#=> [100, 90, 100, 100]
low.values_at(*indices)
#=> [20, 10, 30, 40]
json = {
"groups": [
{ "values": "21", "date": "2013-02-22" },
{ "values": "25", "date": "2013-02-22" },
{ "values": "20", "date": "2013-02-22" },
{ "values": "19", "date": "2013-02-22" },
{ "values": "42", "date": "2013-02-10" },
{ "values": "30", "date": "2013-02-10" },
{ "values": "11", "date": "2013-02-10" }
]
}
dates, low, high = json[:groups].group_by { |g| g[:date] }.map do |date, grouped|
values = grouped.map { |group| group[:values] }
[date, *values.minmax]
end.transpose
# => => [["2013-02-22", "2013-02-10"], ["19", "11"], ["25", "42"]]
dates
# => ["2013-02-22", "2013-02-10"]
low
# => ["19", "11"]
high
# => ["25", "42"]