【问题标题】:Reference .map return object (array) inside that .map code block?在 .map 代码块中引用 .map 返回对象(数组)?
【发布时间】:2014-07-14 16:36:44
【问题描述】:

在 Ruby 中,是否可以从 .map 代码块中引用使用 .map 函数生成的数组对象?

一个非常简单的例子是,如果您尝试只向返回的数组添加唯一元素,并想检查该元素是否已经存在,可能如下所示:

array.map{ |v| v unless (reference to array being created by this map function).include?(v) }

我知道从功能上讲,这段代码是不必要的,因为您可以简单地在数组上使用 .uniq 方法或将值推送到单独的数组中并检查该数组是否已经包含该值,我只是想知道它在概念上是否可行因为我遇到过几次这样的参考资料会很有用。谢谢。

【问题讨论】:

  • reduce, select, reject, each_with_object 更适合这类问题,如果你展示一个用例,你会更容易识别出哪个

标签: ruby arrays loops iteration enumerable


【解决方案1】:

据我所知,地图上没有。但是,您可以使用 reduceinject 来引用该集合。所以:

array.reduce([]) {|memo, v| memo << v unless memo.include? v; memo }

或者……

array.inject([]) do |memo, v| 
    memo << v unless memo.include? v
    memo
end

为了澄清一些关于reduce的问题,reduce的最终返回值变成了memo,但是如果你返回v而不是memo,v变成了memo,它首先传递一个像[1,2, 3,2,1] 将是 1。因此,您的汇总结果将被丢弃。所以你需要将它添加到聚合中并返回聚合。

注意:我同意大多数评论者的观点,uniq 是更好的选择,因为它似乎更明确地表达了意图,而且从性能的角度来看也是如此。详情请见this gist

【讨论】:

  • collectmap 的别名。如果你不能用后者做,那么你也不能用前者做。
  • 谢谢。我忘记了。我认为collect用来别名减少?也许我忘记了为什么将两者联系起来。更新以删除对收集的引用。
  • 是的,所以最终的返回值确实变成了memo,但是如果你返回v而不是memov变成了备忘录,它像[1,2,3,2,1] 这样的数组的第一次传递将是1。因此,您的汇总结果将被丢弃。所以你需要将它添加到聚合中并返回聚合
  • 好的,所以当条件不满足时会出现问题,因此该迭代的返回值(以及下一次迭代期间的累加器)不再是数组。感谢您花时间解释这一点,我真的很感激。
  • @user2017331 谢谢。如果我正在做某种反馈,我倾向于使用inject,如果块的返回值不(或不应该)重要,我倾向于使用each_with_objecteach_with_object 的名称也与块的参数顺序相匹配,这很方便。
【解决方案2】:

我认为如果:

array.map{ |v| v unless (reference to array being created by this map function).include?(v) }

你应该写:

array.uniq

【讨论】:

  • 感谢斯派克曼。我确实在我的问题中解决了这个问题,这更像是一个概念性问题,我用它作为一个非常简单的例子来帮助解释我的问题。
【解决方案3】:

#inject 是最常见的答案,但您也可以考虑#each_with_object

[1,1,3,4].each_with_object([]) {|v, o| o.push(v) unless o.include?(v) }
=> [1, 3, 4]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-28
    • 2020-10-05
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多