Ruby条件映射和替换

时间:2014-12-03 13:51:06

标签: ruby arrays text-manipulation

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

看起来像[“a”,“b”,“c”]

的数组

我想将其内联映射(使用map!)来更改匹配/ 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基础知识。

2 个答案:

答案 0 :(得分:4)

您在select上致电a,该Array会返回map!的新实例,您将在下一步调用a.map! { |e| e =~ /b/ ? 'bb' : e } ,修改此新实例(不是原始实例)一)。要实现您的目标,您可以:

{{1}}

答案 1 :(得分: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方法仅返回 匹配的项目。

一般情况下,不要使用!作为地图,除非你有充分的理由,而且你对它的了解更好,因为修改对象的Ruby !方法往往是更难以调试和可靠地测试。