【问题标题】:How do I use lambdas with arguments to collect an array?如何使用带有参数的 lambda 来收集数组?
【发布时间】:2013-02-14 20:17:31
【问题描述】:

我很好奇如何重构这段代码:

array.collect{|x| x.some_method}.inject(:+) || 0

我在我的代码中使用不同的方法大约有十次,所以我认为我应该重构,但是如何重构?

我尝试了至少十种不同的块、procs 和 lambdas,此时我什至不确定它是否可以重构。

【问题讨论】:

  • 考虑用诸如sum之类的“命名”的东西替换各个部分。名字很好。名称创建隐式文档。如果同一行重复多次,那么这很可能也是“命名”的好候选。
  • “重构”类型的问题可能属于codereview.stackexchange.com。请参阅the CodeReview FAQ 了解更多信息。

标签: ruby lambda mapping block proc


【解决方案1】:

如何重构/重构什么?目标是什么?你想/需要超越:

array.collect(&:some_method).inject(:+) || 0

如果唯一改变的是被调用的方法,则将方法符号传递给方法并在收集期间将其发送给每个对象。

您试图与相关代码进行什么通信?看起来像是某种总结;也许是一个简单的sum 方法,以“属性”名称作为参数?

【讨论】:

  • +1 建议使用名称。我不确定我是否会按照它来提取属性名称,不过:sum people.map(&:age) 或类似的东西对我来说看起来不错。
  • 我们的目标是摆脱这个中间部分,我将其包裹在一个明确命名的函数中
【解决方案2】:

第一次重构:

array.collect(&:some_method).inject(0, :+)

第二次重构,摘要:

module Enumerable
  def sum(method)
    block_given? ? inject(0) { |acc, x| acc + yield(x) } : inject(0, :+)
  end
end

array.map(&:some_method).sum
array.sum(&:some_method)

【讨论】:

    【解决方案3】:

    一个 Ruby 习语是使用:

    array.collect(&:some_method).inject(:+)
    

    in 使用 Symbol#to_proc 方法:http://www.ruby-doc.org/core-1.9.3/Symbol.html#method-i-to_proc

    【讨论】:

      【解决方案4】:

      您首先使用array.collect(&:some_method).inject(:+)。你也可以通过一个inject 调用来做到这一点,如下所示:

      def my_method(ary, method_symbol)
        ary.inject (0) do |sum, elem|
          sum + elem.send( method_symbol )
        end
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        • 1970-01-01
        • 2019-03-31
        • 1970-01-01
        • 2015-08-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多