# Re: Enumerable#collect and #select best practices

**URL:** <https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694>\
**Category:** Ruby\
**Created:** [May 16, 2006, 8:29pm UTC](https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694 "2006-05-16T20:29:46Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![joe-black](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/87869e/32.png) [@joe-black](https://www.ruby-forum.com/u/joe-black)\
**Post date:** [May 16, 2006, 8:29pm UTC](https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694/1 "2006-05-16T20:29:46Z")

</div>

-----Original Message-----  
From: Daniel S. [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

> I need to collect the results of calling a method on each object in an

> Enumerable that defines that method. Currently, I have this:

> enum.collect{|obj| obj.a\_method rescue nil }.compact

> though this could also work:

This looks like prime .inject territory

enum.inject([]) do |l,obj|  
(l \<\< obj.a\_method) if obj.respond\_to? :a\_method  
end

---

<div class="post-metadata">

**Author:** ![joe-black](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/87869e/32.png) [@joe-black](https://www.ruby-forum.com/u/joe-black)\
**Post date:** [May 16, 2006, 8:49pm UTC](https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694/2 "2006-05-16T20:49:40Z")

</div>

Joe B. wrote:

> This looks like prime .inject territory
> 
> enum.inject([]) do |l,obj|  
> (l \<\< obj.a\_method) if obj.respond\_to? :a\_method  
> end

Wonderful!

Now, what if I wanted to generalize it? That is, a method on Enumerable  
that returns an array of the results of calling a a given block with  
each item in the array, excluding the items that do not respond to that  
method.

This is what I’ve got:

module Enumerable  
# need a better name…  
def collect\_x  
collect do |obj|  
begin  
yield obj  
rescue NoMethodError  
nil  
end  
end.compact  
end  
end

Though it’s still verbose…

---

<div class="post-metadata">

**Author:** ![joe-black](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/87869e/32.png) [@joe-black](https://www.ruby-forum.com/u/joe-black)\
**Post date:** [May 16, 2006, 10:45pm UTC](https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694/3 "2006-05-16T22:45:23Z")

</div>

On May 16, 2006, at 2:48 PM, Daniel S. wrote:

> given block with each item in the array, excluding the items that  
> rescue NoMethodError  
> nil  
> end  
> end.compact  
> end  
> end
> 
> Though it’s still verbose…

I don’t think you should use #compact. What if #a\_method happens to  
return nil as a result? Also rescuing NoMethodError, is risky if you  
have a bug inside #a\_method.

I would write it:

module Enumerable  
def selective\_collect(msg\_name, \*args)  
inject([]) do |result\_list, value|  
if value.respond\_to? msg\_name  
result\_list \<\< value.send(msg\_name, \*args)  
end  
result\_list  
end  
end  
end

x = […]  
x.selective\_collect(:a\_method)

of x.selective\_collect(:another\_method, “hello”)

---

<div class="post-metadata">

**Author:** ![joe-black](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/87869e/32.png) [@joe-black](https://www.ruby-forum.com/u/joe-black)\
**Post date:** [May 17, 2006, 12:19am UTC](https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694/4 "2006-05-17T00:19:30Z")

</div>

Logan C. wrote:

> ```
> result_list << value.send(msg_name, *args)
> end
> result_list
> end
> 
> ```
> 
> end  
> end
> 
> x = […]  
> x.selective\_collect(:a\_method)
> 
> of x.selective\_collect(:another\_method, “hello”)

Yeah, I made a similar implementation – it just doesn’t feel Rubyish  
enough not to pass a block to an iterator…

Well, I guess it’s a border case; a general solution is probably not  
needed.

Thanks for your response,  
Daniel

---

<div class="post-metadata">

**Author:** ![joe-black](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/87869e/32.png) [@joe-black](https://www.ruby-forum.com/u/joe-black)\
**Post date:** [May 18, 2006, 6:21pm UTC](https://www.ruby-forum.com/t/re-enumerable-collect-and-select-best-practices/60694/5 "2006-05-18T18:21:54Z")

</div>

In Message-Id: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Logan C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> I don’t think you should use #compact. What if #a\_method happens to  
> return nil as a result? Also rescuing NoMethodError, is risky if you  
> have a bug inside #a\_method.

And if your block given to collect is fairly complex, needless work  
may affects scalability of code. Ie. If the number of items will be  
selected  
are small and a source array is very huge — say, 100 : 10,000,000  
— useless 9,999,900 invocations are avoided if “select then collect”  
approach.
