0

我正在尝试有条件地映射我拥有的数组:

看起来像 [ "a", "b", "c" ] 的数组

我想将它内联映射(使用映射!)以更改匹配 /b/ 的任何内容并将其更改为“bb”。但这似乎不起作用,它似乎并没有改变数组。

我希望它看起来像这样 [ "a", "bb", "c" ]

定义数组:

irb(main):001:0> a = [ "a", "b", "c" ]
=> ["a", "b", "c"]

尝试使用链接到地图的选择!它显示了一个元素的更改值,并且没有更改原始数组。

irb(main):002:0> a.select { |e| e =~ /b/ }.map! { |e| e = "bb" }
=> ["bb"]
irb(main):003:0> p a.inspect
"[\"a\", \"b\", \"c\"]"

所以我尝试做同样的事情,但是将它分配给一个新数组,这只会创建一个包含任何更改元素的数组 - 而不是我想要的

irb(main):004:0> cc = a.select { |e| e =~ /b/ }.map! { |e| e = "bb" } 
=> ["bb"]
irb(main):005:0> p cc.inspect
"[\"bb\"]"
=> nil

我在这里想念什么?我认为我在这里缺少一些 Ruby 基础知识。

4

2 回答 2

4

您调用selecton a,它返回 的新实例Array,在下一步中您调用map!,修改这个新实例(不是原始实例)。要实现您想要的,您可以执行以下操作:

a.map! { |e| e =~ /b/ ? 'bb' : e }
于 2014-12-03T13:52:54.893 回答
3

正确的逻辑如下所示:

results = a.map { |e| if e =~ /b/ then "bb" else e end }

使用三元运算符的相同逻辑:

results = a.map { |e| e =~ /b/ ? "bb" : e }

如果您确实需要就地替换,请!像这样使用:

a.map! { |e| e =~ /b/ ? "bb" : e }

这就是您帖子中的代码未按您预期的方式工作的原因:

  • select正在返回一个新数组,然后map!正在修改新数组。这是一个问题。

  • 更重要的是,该select方法与您使用它的方式不同。该select方法返回匹配的项目。

!通常,除非您有充分的理由,并且您更好地理解它,否则不要使用for map,因为!在适当位置修改对象的 Ruby 方法往往更难以可靠地调试和测试。

于 2014-12-03T13:54:00.250 回答