I am new to Ruby, could someone help?
I have some product data Json that I need to sort by the expiry date, however everything thing I have tried with .sort_by so far is erroring.
The Json is in this format
{"wh_Repeating":[
{
"wh": {
"Item_Number": "111166",
"Expiry_Date": "2023-05-05"
}
},
{
"wh": {
"Item_Number": "111167",
"Expiry_Date": "2023-05-01"
}
},
{
"wh": {
"Item_Number": "111168",
"Expiry_Date": "2023-05-09"
}
}]}
in Ruby that shows as
{:wh_Repeating=>[
{:wh=>{:Item_Number=>"111166", :Expiry_Date=>"2023-05-05"}},
{:wh=>{:Item_Number=>"111167", :Expiry_Date=>"2023-05-01"}},
{:wh=>{:Item_Number=>"111168", :Expiry_Date=>"2023-05-09"}}
]}
tried alsorts latest attempt was
sorted = jsonIn["wh_Repeating"]
sorted.sort_by { |k,v| v[:"Expiry_Date"] }
puts sorted
which gave me undefined method `sort_by' for nil:NilClass (NoMethodError) (Exception)
CodePudding user response:
Your hash keys are symbols not strings.
jsonIn["wh_Repeating"]
should be jsonIn[:wh_Repeating]
Also, sorted.sort_by { |k,v| v[:"Expiry_Date"] }
does not mutate sorted
.
sort_by
does not mutate the receiver. In other words, the value of sorted
remains the same. There is a bang version (sort_by!
) that does mutate (a side-effect) but the use of mutating functions is discouraged.
This does what you want to do.
jsonIn[:wh_Repeating].sort_by { |h| h.dig(:wh, :Expiry_Date) }
CodePudding user response:
I would do it like this:
data = {:wh_Repeating=>
[{:wh=>{:Item_Number=>"111166", :Expiry_Date=>"2023-05-05"}},
{:wh=>{:Item_Number=>"111167", :Expiry_Date=>"2023-05-01"}},
{:wh=>{:Item_Number=>"111168", :Expiry_Date=>"2023-05-09"}}]}
data[:wh_Repeating].sort_by! { |hash| hash[:wh][:Expiry_Date] }
data
#=> {:wh_Repeating=>
[{:wh=>{:Item_Number=>"111167", :Expiry_Date=>"2023-05-01"}},
{:wh=>{:Item_Number=>"111166", :Expiry_Date=>"2023-05-05"}},
{:wh=>{:Item_Number=>"111168", :Expiry_Date=>"2023-05-09"}}]}
CodePudding user response:
I have assumed the original hash (h
below) is not to be mutated (modified).
h = { :wh_Repeating=>[
{:wh=>{:Item_Number=>"111166", :Expiry_Date=>"2023-05-05"}},
{:wh=>{:Item_Number=>"111167", :Expiry_Date=>"2023-05-01"}},
{:wh=>{:Item_Number=>"111168", :Expiry_Date=>"2023-05-09"}}
]
}
As this hash has a single key (:wh_Repeating
), we can simply write the structure of the desired hash as
{ :wh_Repeating=>... }
and then compute the value of :wh_Repeating
.
{ :wh_Repeating=>h[:wh_Repeating].sort_by { |g| g[:wh][:Expiry_Date] } }
#=> { :wh_Repeating=>[
# {:wh=>{:Item_Number=>"111167", :Expiry_Date=>"2023-05-01"}},
# {:wh=>{:Item_Number=>"111166", :Expiry_Date=>"2023-05-05"}},
# {:wh=>{:Item_Number=>"111168", :Expiry_Date=>"2023-05-09"}}
# ]
# }
The original hash h
is unchanged, which can be easily verified.