In Ruby, what is good way to filter all the methods of an object that contain the word "time" in it?
I tried the following and it was partly working:
>> s.methods.map {|n| n if n =~ /time/}
=> [nil, nil, nil, nil, nil, nil, nil, nil, "skip_time_zone_conversion_for_attri
butes", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, ni
l, nil, nil, nil, nil, nil, nil, nil,开发者_JAVA技巧 nil, nil, nil, nil, nil, nil, nil, nil, ni
l, "timestamped_migrations", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "time_zone_aware
_attributes", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "default_timezone", nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, n
il, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "recor
d_timestamps", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil]
>> s.methods.each {|n| p n if n =~ /time/}
"skip_time_zone_conversion_for_attributes"
"timestamped_migrations"
"time_zone_aware_attributes"
"default_timezone"
"record_timestamps"
=> ["extended_by", "before_create", "vote_ids=", "save_without_dirty", "_delete"
, "touch", "daemonize", "after_destroy", "skip_time_zone_conversion_for_attribut
es", "methods", "send", "to_query", "becomes", "after_validation", "store_full_s
ti_class?", "save_with_transactions!", "autosave_associated_records_for_votes",
"require_library_or_gem", "enum_for", "taint", "instance_variable_defined?", "ac
[...] and the rest of the whole array
>> s.methods.filter {|n| n =~ /time/}
NoMethodError: undefined method `filter' for #<Array:0x4de6b00>
from (irb):93
grep
is another easy way to accomplish this:
1.9.0 > require 'date'
=> true
1.9.0 > x = Date.new
=> #<Date: -1/2,0,2299161>
1.9.0 > x.methods.grep /time/
=> ["ctime", "asctime", "strftime"]
With the approaches you tried:
map
applies the given block to each element of the given enumerable, returning a new enumerable. That's not what you wanted here (as you saw).
methods.each
sort of works, but obviously simply printing out the results isn't terribly useful. It wouldn't be Ruby-like at all, but you could have done:
matching_methods = []
s.methods.each {|m| matching_methods << m if m =~ /time/}
to accumulate each method matching /time/
into the matching_methods
array. Of course, if you're doing that, then
s.methods.select { |m| m =~ /time/ }
is preferable.
Lastly, filter
doesn't exist in Ruby; that's what select
(or find_all
) is for.
Use Enumerable.select
s.methods.select{|n| n=~/time/}
Or, use grep
s.methods.grep(/time/)
Here's your approach with compact
:
s.methods.map{|n| n if n =~ /time/}.compact
精彩评论