I'm trying figure out how to pass a statement as a method argument - to be used as part of the block filter criteria. For example, I have the following code:
我正在尝试解决如何将语句作为方法参数传递——作为块筛选标准的一部分。例如,我有以下代码:
def method
other_method.persons.each do |ped|
next if ped.first_name.nil? or ped.last_name.nil?
puts ped.id
puts ped.full_name
end
end
What I'd like to be able to do is as follows (so I can potentially change the filter criteria used in the method). Is it possible to pass a statement including the block reference to the block from a argument?:
我想做的是如下所示(这样我就可以修改方法中使用的筛选条件)。是否可能从参数中传递一个语句,包括块引用到块?
def method(statement)
other_method.persons.each do |ped|
next if statement
puts ped.id
puts ped.full_name
end
end
I appreciate some direction on this.
我很欣赏这方面的一些指导。
2 个解决方案
#1
0
Ped = Struct.new(:first_name, :last_name, :full_name, :id)
# generate some test data
peds = ['Bob', 'Hope', 'Bob Hope', 1, 'Bing', nil, 'Bing Crosby', 2, nil, 'Bacon', 'Kevin Bacon', 3].each_slice(4).map{ |x,y,z,id| Ped.new(x,y,z,id) }
filter_criteria = lambda { |ped| ped.first_name.nil? or ped.last_name.nil? }
peds.find_all(&filter_criteria).each { |ped| p ped }
Output:
输出:
#<struct Ped first_name="Bing", last_name=nil, full_name="Bing Crosby", id=2>
#<struct Ped first_name=nil, last_name="Bacon", full_name="Kevin Bacon", id=3>
Change out filter_criteria with another Proc/lambda to change the filtering. An alternative is to wrap the find_all in a method to take a filtering block like this:
使用另一个Proc/lambda更改filter_criteria以更改过滤。另一种方法是将find_all封装在一个方法中,以使用这样的过滤块:
def filter list, &criteria
list.find_all(&criteria)
end
filter(pedlist) { |ped| some filter criteria }.each { |ped| do something }
and the resulting enumerable can then be used as needed.
然后可以根据需要使用结果可枚举值。
#2
6
You don't pass "statements" you pass blocks. A passed block is called via yield
or captured into a proc and called with Proc#call
.
你不会传递“语句”,而是传递块。传递的块通过yield或捕获到proc调用,并通过proc #调用调用。
def method
other_method.persons.each do |ped|
next if yield(ped)
puts ped.id
puts ped.full_name
end
end
method { |ped| ped.first_name.nil? or ped.last_name.nil? }
#1
0
Ped = Struct.new(:first_name, :last_name, :full_name, :id)
# generate some test data
peds = ['Bob', 'Hope', 'Bob Hope', 1, 'Bing', nil, 'Bing Crosby', 2, nil, 'Bacon', 'Kevin Bacon', 3].each_slice(4).map{ |x,y,z,id| Ped.new(x,y,z,id) }
filter_criteria = lambda { |ped| ped.first_name.nil? or ped.last_name.nil? }
peds.find_all(&filter_criteria).each { |ped| p ped }
Output:
输出:
#<struct Ped first_name="Bing", last_name=nil, full_name="Bing Crosby", id=2>
#<struct Ped first_name=nil, last_name="Bacon", full_name="Kevin Bacon", id=3>
Change out filter_criteria with another Proc/lambda to change the filtering. An alternative is to wrap the find_all in a method to take a filtering block like this:
使用另一个Proc/lambda更改filter_criteria以更改过滤。另一种方法是将find_all封装在一个方法中,以使用这样的过滤块:
def filter list, &criteria
list.find_all(&criteria)
end
filter(pedlist) { |ped| some filter criteria }.each { |ped| do something }
and the resulting enumerable can then be used as needed.
然后可以根据需要使用结果可枚举值。
#2
6
You don't pass "statements" you pass blocks. A passed block is called via yield
or captured into a proc and called with Proc#call
.
你不会传递“语句”,而是传递块。传递的块通过yield或捕获到proc调用,并通过proc #调用调用。
def method
other_method.persons.each do |ped|
next if yield(ped)
puts ped.id
puts ped.full_name
end
end
method { |ped| ped.first_name.nil? or ped.last_name.nil? }