Ruby 一点 map 的心得

lithium4010 · 2015年12月14日 · 最后由 crazyjin 回复于 2015年12月15日 · 2725 次阅读

有个数组

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

我们想生成一个把 numbers 中每个值映射到 String 的 Array , 通常我们这么做

numbers.map { |number| number.to_s }

简写就是这样

numbers.map(&:to_s)

现在有一个名字的数组

names = %w[女朋友 小二 小三 小四 小五 小六 小七 小八 小九 小十]

我们想根据 numbers 在 names 中的位置找到对应的名字,通常我们这么做

numbers.map { |number| names[number - 1] }  # 程序员从 0 开始数数

花括号好烦不想写花括号

numbers.map(&names.method(:[]))

诶不对没有减 1,没关系可以这样

numbers.map { |number| number - 1 }.map(&names.method(:[]))

我去还是有花括号,那这样

minus_one = -> (number) do 
  number - 1
end

numbers.map(&minus_one).map(&names.method(:[]))

do ... end 和花括号没有区别啊

numbers.map(&1.method(:-)).map(&0.method(:-)).map(names.method(:[]))

至于如何 map 一个 Object 上的方法 并给这个方法传递一个值作为参数,不存在多态的时候可以这样

class Object
  def self.pure_instance_method(name)
    ->(*args) { 
      ->(obj) {
        self.instance_method(name).bind(obj)[*args]
      }
    }
  end
end

names.map(&String.pure_instance_method(:[])[-1]) # 所有名字的最后一个字

存在多态或者不知道数组中元素类型的时候我就不会了,这里抛砖引个玉 ~

感觉过度编码了

numbers.map { |number| names[number - 1] } 

不觉得这个最简洁明了吗

好像可以这样

class Object
  def lazy_send(method_name, *args)
    ->(obj=self) { obj.send method_name, *args }
  end
end

names.map(&lazy_send(:[], -1)) # 所有名字的最后一个字

#1 楼 @kikyous Just 4 fun. 有些情况下还是有用滴。

楼主真是喜欢追求极致 +1

ruby 被你玩坏了

如果只是简单的用,如

numbers.map(&:to_s)

我很喜欢,因为还可以这样:

numbers.map(&:to_s).uniq

因为如果用{}

numbers.map {|e| e.to_s}.uniq

就难看了

太复杂的,限于智商,不想用

7 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号