user
user

Reputation: 1381

Replace hash value

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

Answers (3)

Aleksei Matiushkin
Aleksei Matiushkin

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

Lukas Baliak
Lukas Baliak

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

Larry Lv
Larry Lv

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

Related Questions