如何过滤掉数组

时间:2016-08-16 20:08:47

标签: ruby-on-rails arrays ruby

我有一行代码迭代数组并拒绝所有空元素:

survey.reject!(&:empty?).map! { |feedback| %(_"#{feedback}"_) }

如果整个数组为空,则按预期工作。如果数组中的某个元素不为空,则会出现错误map!不存在。

然而,这没有问题:

survey.map! { |feedback| %(_"#{feedback}_") }

当整个数组为空时reject函数有效,而当数组不为空时map!版本有效。我怎样才能最好地巩固这些?

2 个答案:

答案 0 :(得分:4)

使用就地修饰符时必须小心。正如the documentation for reject! says

  

删除块评估为{em> true 的self的每个元素,如果未进行任何更改,则返回nil

由于该功能,您不能像可以复制的版本那样链接这些。

你可以做的是两行:

survey.reject!(&:empty?)
survey.map! { |feedback| %(_"#{feedback}"_) }

或者你可以重新分配:

survey = survey.reject(&:empty?).map { |feedback| %(_"#{feedback}"_) }

答案 1 :(得分:3)

Array#reject!如果没有更改任何内容,则会返回nilnil没有map!方法,因此您获得NoMethodError

为什么还要链接副作用方法?副作用方法的目的是它的副作用,而不是它的返回值。你可以做到

survey.reject!(&:empty?)
survey.map! { |feedback| %(_"#{feedback}"_) }

或者,更好的是:不要使用副作用。他们是邪恶的。

survey = survey.reject(&:empty?).map { |feedback| %(_"#{feedback}"_) }

但是,请注意,执行与上述操作相同的操作:上述操作会使survey引用的单个对象发生变异。这会改变引用survey本身并使其指向不同的对象。

整体上这个更干净,但如果你的系统中有其他代码依赖于可变的共享状态和副作用,那么它也必须改变。