0

The values in my hash are either a nested hash:

test_multiple_hash = { test: { another_test: 123 } }

or an array of hashes:

test_multiple_hash = { test: [{ another_test: 123 }, { another_test: 124 }] }

After having fetched a value, I need to use #select to find specific nested hashes:

test_multiple_hash[:test].select { |s| s[:another_test] == 123 }

If my hash has only a single hash, then select doesn't suite my needs unless I convert the single hash into an array.

Is there a better way to find an object by the value to a key when the value to a key in the hash is a single hash or an array of hashes?

7
  • What is test_multiple_hash? Commented Jul 20, 2015 at 11:01
  • cool, downvote without a reason why? Commented Jul 20, 2015 at 11:01
  • What is your expected result with the simpler (nested hash) case? Commented Jul 20, 2015 at 11:01
  • it's the value of either of the two possible search results, if you read the key I am trying to select to you should relate it to the example of hashes i was referring to... Commented Jul 20, 2015 at 11:02
  • 1
    This seems pretty clear to me. I've edited your question pretty heavily to better reflect what I think you mean. If I have erred, then will you please revert my edit? Commented Jul 20, 2015 at 12:24

3 Answers 3

2

I would suggest you to start with making all the underlying values of common pattern:

hash = { test: { another_test: 123 },
         test2: { test: [{ another_test: 123 }, { another_test: 124 }] }
       }

hash.map { |k, v| [k, [*v]] }.to_h # now all of them are arrays.

And then do whatever you want, assuming that the values are definitely arrays, e. g.:

hash.map do |k, v|
  [k, [*v]]
end.to_h[:test].select do |s| 
  s[:another_test] == 123
end
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, this does help me solve my problem and helped me realise efficient ways of dealing with different data models throughout my codebase...
1

You could do

[my_hash[:test]].flatten.select { |s| s[:another_test] == 123 }

1 Comment

This suite my needs for this particular problem, other solutions also do the trick but this one looks cleaner for the problem above! thanks for your suggestion! I am now applying it =)
1

The method Kernel#Array will convert its argument to an array:

2.2.1 :002 > Array(1)
 => [1] 

unless the argument already is an array; then it returns the argument unchanged:

2.2.1 :003 > Array([1])
 => [1] 

So you can use the Array function to force test_multiple_hash[:test] to be an array:

Array(test_multiple_hash[:test]).select { |s| s[:another_test] == 123 }

The result of #select will always be an array, even if test_multiple_hash[:test] was not an array.

Comments

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.