-----Original Message-----
From: Daniel S. [mailto:[email protected]]
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
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…
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”)
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
In Message-Id: [email protected]
Logan C. [email protected] 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.