1

I have a hash:

{
  "grey" => ["anf_94748_01_prod1", "anf_94748_01_model1", "anf_94748_01_model2"],
  "heather blue" => ["anf_106537_01_prod1", "anf_106537_01_model1", "anf_106537_01_model2"],
  "indigo" => [],
  "dark grey" => ["anf_94747_01_prod1"]
}

How can I replace its values according to an array of image ids:

[317, 318, 319, 320, 340, 358, 365]

If hash array is empty, then skip it and go to the next hash key, and assign id to that image. Desired output will be:

{
  "grey" => [317, 318, 319],
  "heather blue" => [320, 340, 358],
  "indigo" => [],
  "dark grey" => [365]
}
1
  • Igor, I have two suggestion: 1) format your code so that readers can read it without having to scroll horizontally; and 2) assign each example input (here just one hash) to a variable, so that readers can refer to those variables in comments and answers without having to define them. For example, h = { "grey"=>...}. Commented Oct 11, 2015 at 17:08

3 Answers 3

3
h = {
  "grey" => ["anf_94748_01_prod1", "anf_94748_01_model1", "anf_94748_01_model2"],
  "heather blue" => ["anf_106537_01_prod1", "anf_106537_01_model1", "anf_106537_01_model2"],
  "indigo" => [],
  "dark grey" => ["anf_94747_01_prod1"]
}
a = [317, 318, 319, 320, 340, 358, 365]

h.each_value{|v| v.map!{a.shift}}
# =>
# {
#   "grey"=>[317, 318, 319],
#   "heather blue"=>[320, 340, 358],
#   "indigo"=>[],
#   "dark grey"=>[365]
# }
Sign up to request clarification or add additional context in comments.

1 Comment

Good. Alternatively, v.replace(a.shift(v.size)).
1

As a variant of @sawa's answer, if you do not wish to mutate h, the OP's example hash, you could do this:

a = [317, 318, 319, 320, 340, 358, 365]

h.merge(h) { |_,v| a.shift(v.size) }
   #=> {"grey"=>[317, 318, 319], "heather blue"=>[320, 340, 358],
   #    "indigo"=>[], "dark grey"=>[365]

This uses the form of Hash#merge that employs a block to determine the values of keys present in both hashes, which here is all keys.

Comments

0

reduce is a good function for taking moving through a data structure while accumulating some result.

imgs = [317, 318, 319, 320, 340, 358, 365]
input = {"grey"=>["anf_94748_01_prod1", "anf_94748_01_model1", "anf_94748_01_model2"], "heather blue"=>["anf_106537_01_prod1", "anf_106537_01_model1", "anf_106537_01_model2"], "indigo"=>[], "dark grey"=>["anf_94747_01_prod1"]}

input.reduce({}) { |acc, (k, xs)| acc[k] = imgs.shift(xs.count); acc}

# => {"grey"=>[317, 318, 319], "heather blue"=>[320, 340, 358], "indigo"=>[], "dark grey"=>[365]} 

1 Comment

Or preferably Enumerable#each_with_object since it exactly fits your description unlike Enumerable#reduce.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.