7

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

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

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;
}
4

5 回答 5

11

I suppose that by [1,2,3,4].mapp("cat") you mean [1,2,3,4].mapp{"cat"}.

That said, map without a block returns an enumerator:

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

That is the same output of to_enum

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

So in your code, you just want to call 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
于 2013-05-07T15:36:13.817 回答
1

rubinius有一个尽可能用 ruby​​ 编写的 ruby​​ 实现。您可以查看他们的代码以获取enumerable.#collect

有趣的是两者之间的区别

于 2013-05-07T16:41:43.337 回答
1
return to_enum :mapp unless block_given?    

应该足够了。

请参阅完全在 Ruby 中的 Rubinius 实现的 map 的实现:

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
于 2013-05-07T15:38:04.660 回答
1
class Array
  def map!
    return to_enum :map! unless block_given?
    self.each_with_index { |e, index| self[index] = yield(e) }
  end
end
于 2017-11-07T21:57:23.117 回答
-1

查看文档Object#to_enum

于 2013-05-07T15:35:18.810 回答