【问题标题】:Ruby - Select modified values from array based on some conditionRuby - 根据某些条件从数组中选择修改后的值
【发布时间】:2014-01-24 19:04:58
【问题描述】:

我知道在 Ruby 中如何选择、收集和映射。我只是想知道是否有类似的原生 Ruby 方法可以组合它们并在一次迭代中给出结果,而无需从数组中删除 nil?

例如

(1..10).map { |x| x*3 if x.even? }.compact
(1..10).select { |x| x.even? }.map{ |x| x*3 }
(1..10).select { |x| x.even? }.collect{ |x| x*3 }

都给出相同的结果,即 [6, 12, 18, 24, 30]。但是是否有 'some_method' 给出了相同的结果?

(1..10).some_method { |x| x*3 if x.even? }  ## evaluates to [6, 12, 18, 24, 30]

【问题讨论】:

  • 后两个例子可以缩短,例如(1..10).select(&:even?).map{ |x| x*3 },这让它们非常简洁。
  • Ruby 与大多数语言一样,为我们提供了基本的构建块,我们用它来构建更复杂的功能。当我们想做更复杂的事情但隐藏复杂性时,我们定义了一个方法来做到这一点。许多 Ruby 的内置方法就是这样做的。查看它们的来源,您会看到用于增加额外生物舒适度的原语,因为有人看到了需求。
  • 您有什么特别的原因要在这里使用一种方法而不是两种方法吗? IMO,所有这些示例都非常清楚,除非您在大型阵列上运行它们,否则性能不太可能成为主要问题。
  • 根据我自己的经验,如果你必须使用compact 来清理map 操作,那么很有可能真的你做错了什么。 map 应该为传入的每个值发出一个有用且预期的返回值。
  • @Ajedi32优化不是减少代码行数,也不是减少方法链,你需要一个benchmark才能真正知道哪个更快(这就是优化)

标签: ruby ruby-1.8.7


【解决方案1】:

Enumerable#each_with_object

(1..10).each_with_object([]) { |x,arr| arr.push(x*3) if x.even? }  ## evaluates to [6, 12, 18, 24, 30]

【讨论】:

  • 我会用(1..10).each_with_object([]){ |x, a| a << x*3 if x.even? } # => [6, 12, 18, 24, 30] 写这个。我发现使用<<push 更具可读性,否则就是一回事。
【解决方案2】:

你可以使用reduce:

(1..10).reduce([]){ |a,x| a << x*3 if x.even?; a }

或(等价,同样令人困惑):

(1..10).reduce([]){ |a,x| x.even? ? a << x*3 : a }

【讨论】:

  • 在类似的情况下,以下方法也有效:(1..10).inject([]){ |a,x| a &lt;&lt; x*3 if x.even?; a } 但我不确定这是否是正确的做法。
  • 同意。任何这些工作 - 它们可能比 select + map 稍微快一点,但它们并不容易阅读,我宁愿优化可读性而不是假设的速度。
  • 考虑使用each_with_object 而不是reduceinjecteach_with_object 不需要每次注入的对象都由块返回,这通常会使它更干净。
猜你喜欢
  • 2020-10-01
  • 2022-09-23
  • 2012-10-16
  • 2016-10-17
  • 1970-01-01
  • 2015-03-13
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多