0

I have a collection of objects with certain attributes. I also have a CONSTANT array of ids.

I want to return the whole objects who have an id that exists in the constant array.

This is what I have so far, but it just returns true or false for each, I need it to return an array of all the objects:

some_object_attributes.collect { |attr| (Constant::SOME_IDS.include? attr.object.object_type_id)}

How can I return every attr.object which has an ID in the constant array?

3
  • How many ids are there in the constant? What is the size of the object array? Using a Set instead of an array might improve the performance a lot. Commented Apr 19, 2017 at 16:49
  • 1
    Is there a reason this cannot be a query parameter? something like scope :in_constant_array, -> { where( object_type_id: Constant::SOME_IDS)} then you can leverage SQL to do the lifting rather than in mem Commented Apr 19, 2017 at 17:19
  • There is only a dozen or so IDs in the constant.. Commented Apr 19, 2017 at 21:33

3 Answers 3

3

You don't want to do a collect (aka map), which returns the result of the block. You want to return the object in the collection based on the result of the block. For that, there's select:

some_object_attributes.select do |attr| 
  Constant::SOME_IDS.include? attr.object.object_type_id
end
Sign up to request clarification or add additional context in comments.

Comments

3

Just out of curiosity, for a really huge array that way it might be faster:

some_object_attributes.group_by do |attr|
  attr.object.object_type_id
end.values_at(*Constant::SOME_IDS).flatten

This is O(N) because it does not look up the Constant::SOME_IDS array for each element.

3 Comments

I suck at algorithmic complexity, but doesn't values_at do a similar thing behind the scenes, iterating and matching? It's surely faster than doing so in Ruby, but still affects your cost.
@coreyward it looks up the hash, it is promised to be O(1).
Ohhh that's right because the hash lookup table is divided by bitwise hashing and the full table isn't scanned. Awesome.
0

Use select instead of collect.

collect is returning the result of the evaluation (true or false). select will return the objects.

This article may be of use.

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.