在多次映射/过滤器调用后获取初始值



我有一个经过几个转换步骤和最后一个筛选步骤的枚举

例如

[1,2,3,4,5,6,7,8,9].map{|i| i * 2}
.map{|i| i * i}
.filter{|i| i % 3 ==0 }
.each{|i| puts how_do_i_get_initial_value_here }
.or_the_initial_value_here

如何获取转换满足筛选器的初始值?

因此,在上面的例子中,我如何最终得到[3,6,9]而不是[36, 144, 324]

您可以直接在filter中应用在两个map调用中执行的转换:

[1,2,3,4,5,6,7,8,9]
.filter { |i| (i * 2)**2 % 3 == 0 }

或者,您可以将原始值保留在"元组"中,如下所示:

[1,2,3,4,5,6,7,8,9]
.map { |i| [i, i] }
.map { |a, b| [a, b * 2] }
.map { |a, b| [a, b * b] }
.filter { |a, b| b % 3 == 0 }
.map { |a, _| a }

您需要将原始值带到最后一步。

面向对象的方法可以通过引入"过滤器"类型来提供帮助

class Filter
attr_reader :value
def initialize(value)
@value = value 
end
def satisfies?
(value * 2 * value) % 3 == 0
end
end

用法

[1,2,3,4,5,6,7,8,9].map { |i| Filter.new(i) }.select(&:satisfies?).map(&:value)

给你一个方法:

def f(n)
4 * n**2
end

其中f(n)是从给定数组n的元素的转换值(如(2 * n)*(2 * n) = 4 * n**2)(。

f是 1-1 映射,因此它有一个反方法g(即,g(f(n)) #=> n对于所有整数n(:

def g(m)
Math.sqrt(m).round/2
end

(我们需要.round,因为舍入误差。

假设我们有:

arr
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

然后

z = arr.map { |n| f(n) }.filter { |x| x % 3 == 0 }
#=> [36, 144, 324] 

然后这些值的倒数由下式给出:

z.map { |m| g(m) }
#=> [3, 6, 9]

请注意:

arr.map { |n| f(n) }.filter { |x| x % 3 == 0 }

与以下相同:

arr.filter { |x| x % 3 == 0 }.map { |n| f(n) }

你可以撤消你所做的事情。所以

[1,2,3,4,5,6,7,8,9]
.map{ |i| i * 2 }
.map{ |i| i * i }
.filter{ |i| i % 3 ==0 }
.map{ |i| Math.sqrt(i) / 2 }

最新更新