在Ruby中重新实现Enumerable Map方法

时间:2013-05-07 15:26:37

标签: ruby-on-rails ruby map

我正在红宝石店练习实习。我期待的一个工作问题是重新实现一个可枚举的方法。

我正在尝试立即实现地图,我无法弄清楚如何实现没有给出块的情况。

class Array
    def mapp()
      out = []
      if block_given?
        self.each { |e| out << yield(e) }
      else
        <-- what goes here? -->
      end
   out
   end
 end

使用我当前的实现。如果我跑:

[1,2,3,4,5,6].mapp{|each| each+1} #returns => [2,3,4,5,6,7]

但是,我不确定如何获取未传入块的情况:

[1,2,3,4].mapp("cat") # should return => ["cat", "cat", "cat", "cat"]

如果有人能指出我正确的方向。我真的很感激。我尝试查看源代码,但似乎做的事情与我以前的做法截然不同。

static VALUE
enum_flat_map(VALUE obj)
{
VALUE ary;

RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

ary = rb_ary_new();
rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);

return ary;
}

5 个答案:

答案 0 :(得分:7)

我认为[1,2,3,4].mapp("cat")代表[1,2,3,4].mapp{"cat"}

也就是说,没有块的map返回一个枚举器:

 [1,2,3,4].map
 => #<Enumerator: [1, 2, 3, 4]:map>

这与to_enum

的输出相同
[1,2,3,4].to_enum
 => #<Enumerator: [1, 2, 3, 4]:each> 

所以在你的代码中,你只想调用to_enum:

class Array
    def mapp()
        out = []
        if block_given?
            self.each { |e| out << yield(e) }
        else
            out = to_enum :mapp
        end
        out
    end
end

答案 1 :(得分:1)

return to_enum :mapp unless block_given?    

应该足够了。

请参阅完全使用Ruby的Rubinius实现的地图实现:

https://github.com/rubinius/rubinius/blob/master/kernel/bootstrap/array19.rb

# -*- encoding: us-ascii -*-

class Array
  # Creates a new Array from the return values of passing
  # each element in self to the supplied block.
  def map
    return to_enum :map unless block_given?
    out = Array.new size

    i = @start
    total = i + @total
    tuple = @tuple

    out_tuple = out.tuple

    j = 0
    while i < total
      out_tuple[j] = yield tuple.at(i)
      i += 1
      j += 1
    end

    out
  end
end

答案 2 :(得分:1)

使用rubinius,有一个ruby实现,尽可能用ruby编写。您可以查看可枚举的代码。#collect

有趣的是

之间的区别

答案 3 :(得分:1)

class Array
  def map!
    return to_enum :map! unless block_given?
    self.each_with_index { |e, index| self[index] = yield(e) }
  end
end

答案 4 :(得分:-1)

查看Object#to_enum

的文档