【问题标题】:Return a new array modified from a block/yield in ruby返回从 ruby​​ 中的块/产量修改的新数组
【发布时间】:2015-10-02 11:01:37
【问题描述】:

我刚刚在 bloc.io 开始了全栈开发人员课程,我正在努力完成一项任务。我似乎找不到我的代码的问题,但我也有点不清楚任务可能要求什么。任何指导将不胜感激。作业给出了以下示例。对于这篇文章的篇幅,我深表歉意,但我想尽可能详尽。

  def return_bigger(array)
      array.map do |item|
        yield(item)
      end
    end

return_bigger([1,2,3,4]) do |item|
  item + 1000
end
#=> [1001, 1002, 1003, 1004] 

return_bigger(["cat", "hat", "bat"]) do |item|
  item.capitalize
end
#=> ["Cat", "Hat", "Bat"]

new_each([1,2,3,4]) do |item|
  p "Whatever I want! Item: #{item}"
end

def new_each(array)
  0.upto(array.length - 1) do |index|
    yield( array[index] )
  end
end

然后将赋值描述如下:

定义一个 new_map 函数。它应该将一个数组作为参数并返回一个根据作为块传入的指令修改的新数组。随意在方法中使用每个,而不是我们上面使用的数组索引。

重新实现map的第一步应该是遍历数组:

def new_map(array)
  array.each do |item|
  end
end

new_map 方法与我们的 new_each 方法非常相似,但不仅仅是对每个元素执行“副作用”行为,您需要将每个块调用的返回值存储在一个新数组中:

def new_map(array)
  new_array = []
  array.each do |item|
    # invoke the block, and add its return value to the new array
  end
end

完成对旧数组的迭代后,只需从 new_map 函数中返回新数组即可。

据我所知,作业要我在不使用 .map 的情况下复制 new_each 方法,然后将其存储在“new_array”中。但是,我不确定我的代码中的缺陷是什么。我的代码没有“屈服”我定义的块是否有原因?这是我想出的代码:

def new_map(array)
  new_array = []
  array.each do |item|
    yield(item)
    new_array << item
  end
end

new_map([1,2,3,4]) do |item|
  item + 1
end

new_map(["cat", "hat", "bat"]) do |item|
  item.capitalize
end

作业:

 new_map should not call map or map!

RSpec::Expectations::ExpectationNotMetError

expected: [2, 3, 4]
     got: [1, 2, 3]

(compared using ==)

exercise_spec.rb:9:in `block (2 levels) in <top (required)>'

 new_map should map any object
RSpec::Expectations::ExpectationNotMetError

expected: [Fixnum, String, Symbol]
     got: [1, "two", :three]

(compared using ==)

exercise_spec.rb:14:in `block (2 levels) in <top (required)>'

规格:

describe "new_map" do
  it "should not call map or map!" do
    a = [1, 2, 3]
    a.stub(:map) { '' }
    a.stub(:map!) { '' }

    expect( new_map(a) { |i| i + 1 } ).to eq([2, 3, 4])
  end

  it "should map any object" do
    a = [1, "two", :three]
    expect( new_map(a) { |i| i.class } ).to eq([Fixnum, String, Symbol])
  end
end

【问题讨论】:

  • 您犯了一个非常小的错误:您忘记在方法结束时返回new_array。目前正在返回each的接收者:[1,2,3]。只需在最后一行添加new_array
  • 即使我这样做了,我仍然得到同样的错误。知道为什么吗?
  • 试试这个:def new_map(array); new_array = []; array.each { |item| new_array &lt;&lt; yield item }; new_array; end。 (注意,在 cmets 中编写代码时需要分号,而当执行的最后一条语句的值是您想要返回的值时(如这里),则不需要 return
  • @CarySwoveland 谢谢!

标签: ruby methods yield


【解决方案1】:

两个小错误:事实上,您将 new_array 填充了原始项目,而不是从 yield item 获得的转换后的项目,并且(正如 Cary Swoveland 在 cmets 中已经提到的)没有返回 @ 987654323@。实际上,您正在返回最后一个计算值,它是 array.each 的结果,即 array - 因此,您返回的是原始数组,而不是您的计算结果。这就是为什么您在期待[1+1, 2+1, 3+1] 时收到[1, 2, 3]

【讨论】:

  • !谢谢!那成功了。我整天都在这样做。我开始失去理智了。
  • 认为自己正在失去理智是没有头绪的,所以你正在取得进步。恭喜!
【解决方案2】:
def new_map(array)
  new_array = []
  array.each do |item|
    yield(item)
    new_array << yield(item)
  end
  new_array
end

new_map([1,2,3,4]) do |item|
  item + 1
end

new_map(["cat", "hat", "bat"]) do |item|
  item.capitalize
end

【讨论】:

  • 如果你在代码块中有副作用,双重收益可能会带来意想不到的怪异。
  • 很高兴知道!我没有意识到我只需要一个收益。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 2011-03-05
  • 2017-06-08
  • 1970-01-01
  • 2016-11-18
相关资源
最近更新 更多