Reputation: 1381
I have an array of hashes:
[{"__content__"=>"Guitars", "id"=>"2"},
{"__content__"=>"For Guitars", "id"=>"3", "parentId"=>"2"},
{"__content__"=>"6-string", "id"=>"24", "parentId"=>"2"},
{"__content__"=>"7-string", "id"=>"25", "parentId"=>"2"},
{"__content__"=>"8-string", "id"=>"26", "parentId"=>"2"}]
I want to replace the parentId
values with the __content__
values to get:
[{"__content__"=>"Guitars", "id"=>"2"},
{"__content__"=>"For Guitars", "id"=>"3", "parentId"=>"Guitars"},
{"__content__"=>"6-string", "id"=>"24", "parentId"=>"Guitars"},
{"__content__"=>"7-string", "id"=>"25", "parentId"=>"Guitars"},
{"__content__"=>"8-string", "id"=>"26", "parentId"=>"Guitars"}]
How can I do it?
Upvotes: 0
Views: 486
Reputation: 121000
Beware! The solution below mutates the original hash!
▶ hashes = [{"__content__"=>"Guitars", "id"=>"2"},
▷ {"__content__"=>"For Guitars", "id"=>"3", "parentId"=>"2"},
▷ {"__content__"=>"6-string", "id"=>"24", "parentId"=>"2"},
▷ {"__content__"=>"7-string", "id"=>"25", "parentId"=>"2"},
▷ {"__content__"=>"8-string", "id"=>"26", "parentId"=>"2"}]
hashes.each_with_object({}) do |h, memo|
memo[h['id']] = h['__content__']
h['parentId'] = memo[h['parentId']]
end
hashes
#⇒ [{"__content__"=>"Guitars", "id"=>"2", "parentId"=>nil},
# {"__content__"=>"For Guitars", "id"=>"3", "parentId"=>"Guitars"},
# {"__content__"=>"6-string", "id"=>"24", "parentId"=>"Guitars"},
# {"__content__"=>"7-string", "id"=>"25", "parentId"=>"Guitars"},
# {"__content__"=>"8-string", "id"=>"26", "parentId"=>"Guitars"}]
Upvotes: 1
Reputation: 2869
I prefer to change this nasted array
to hash
for better maping.
input
arr = [
{"__content__" => "Guitars", "id" => "2"},
{"__content__" => "For Guitars", "id" => "3", "parentId" => "2"},
{"__content__" => "6-string", "id" => "24", "parentId" => "2"},
{"__content__" => "7-string", "id" => "25", "parentId" => "2"},
{"__content__" => "8-string", "id" => "26", "parentId" => "2"}
]
create parents
parents = arr.each_with_object({}) { |h, exp| exp[h['id']] = h['__content__'] }
After this good map structure you can use simply map
method.
process
output = arr.map do |h|
h['parentId'] = parents[h['parentId']] if h['parentId'] && parents[h['parentId']]
h
end
output
p output
# [
# {"__content__" => "Guitars", "id" => "2"},
# {"__content__" => "For Guitars", "id" => "3", "parentId" => "Guitars"},
# {"__content__" => "6-string", "id" => "24", "parentId" => "Guitars"},
# {"__content__" => "7-string", "id" => "25", "parentId" => "Guitars"},
# {"__content__" => "8-string", "id" => "26", "parentId" => "Guitars"}
# ]
I hope this helps.
EDIT
You can also use this way
sort by ID
arr.sort_by! { |h| h['id'] }
process
output = arr.each_with_object({}) do |h, exp|
exp[h['id']] = h
h['parentId'] = exp[h['parentId']]['__content__'] if h['parentId'] && exp[h['parentId']]
h
end
after this you will have hash with id like keys, so for your output:
output
p output.values
# [
# {"__content__"=>"Guitars", "id"=>"2"},
# {"__content__"=>"6-string", "id"=>"24", "parentId"=>"Guitars"},
# {"__content__"=>"7-string", "id"=>"25", "parentId"=>"Guitars"},
# {"__content__"=>"8-string", "id"=>"26", "parentId"=>"Guitars"},
# {"__content__"=>"For Guitars", "id"=>"3", "parentId"=>"Guitars"}
# ]
Upvotes: 4
Reputation: 769
arr = [{"__content__"=>"Guitars", "id"=>"2"}, {"__content__"=>"For Guitars", "id"=>"3", "parentId"=>"2"}]
id_content_mapping = arr.reduce({}) do |h, elt|
h[elt["id"]] = elt["__content__"]
h
end
arr.map do |elt|
if elt.has_key? "parentId"
elt["parentId"] = id_content_mapping[elt["parentId"]]
end
elt
end
Upvotes: 0