(1..4).collect do |x|
next if x == 3
x + 1
end # => [2, 3, nil, 5]
# desired => [2, 3, 5]
如果next
条件满足,collect
提出nil
在阵列中,而我想要做的就是把没有元素返回数组中如果条件满足。这可能不会在返回的数组上调用delete_if { |x| x == nil }
?跳过迭代收集
(使用Ruby 1.8.7;我的代码摘录在很大程度上抽象)
(1..4).collect do |x|
next if x == 3
x + 1
end # => [2, 3, nil, 5]
# desired => [2, 3, 5]
如果next
条件满足,collect
提出nil
在阵列中,而我想要做的就是把没有元素返回数组中如果条件满足。这可能不会在返回的数组上调用delete_if { |x| x == nil }
?跳过迭代收集
(使用Ruby 1.8.7;我的代码摘录在很大程度上抽象)
有方法Enumerable#reject
供应只是目的:
(1..4).reject{|x| x == 3}.collect{|x| x + 1}
直接使用一种方法的输出作为另一个输入的做法被称为方法链式,是非常在Ruby中很常见。
顺便说一句,map
(或collect
)用于输入enumerable直接映射到输出。如果您需要输出不同数量的元素,则可能需要使用另一种方法Enumerable
。
编辑:如果你是一个事实,即某些元素被重复两次困扰,您可以使用基于较少优雅的解决方案inject
(或其类似方法命名each_with_object
):
(1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3}
我会简单地调用.compact
所得阵列,这消除零的任何实例中的阵列上。如果你想它修改现有的阵列(没有理由不),使用.compact!
:
(1..4).collect do |x|
next if x == 3
x
end.compact!
我做了一个快速基准,利息,这四个解决方案的建议至今:收集+压缩,收集+紧凑!拒绝+收集并将结果数组构建为y你去吧。在MRI 1.9.1中,至少收集+紧凑!是一个狭窄的优势,收集+紧凑和拒绝+收集在后面很接近。建立结果数组的速度大约是那些速度的两倍。 – 2011-03-01 14:01:18
@glenn:你介意在你的基准测试中包括以下内容:'(1..4).inject([]){| a,x | x == 3? a:a.push(x + 1)}?谢谢。 – 2011-03-01 14:59:51
当然。这是最慢的一个,虽然只比构建结果数组稍慢一点。我还添加了一个像这样调整的版本:'a.inject([]){| aa,x | aa << x + 1,除非x == 3; aa}',这比构建阵列要快,但仍然比三种快速方法慢得多。 – 2011-03-01 18:07:55
我会建议使用:
(1..4).to_a.delete_if {|x| x == 3}
,而不是收集+下一条语句。
_real_代码比我的问题中的抽象代码更复杂,所以这不会实现我正在寻找的东西,不幸的是。 (该收集实际上操纵的价值,而不是仅仅返回它) – 2011-03-01 08:53:39
好吧,所以建议的契约!解决方案就是你的选择。 – ALoR 2011-03-01 08:55:36
只是一个建议,你为什么不这样做:
result = []
(1..4).each do |x|
next if x == 3
result << x
end
result # => [1, 2, 4]
以这种方式保存的另一次迭代,除去从零数组元素。希望它有助于=)
这就像Mladen的“拒绝”示例的更详细的版本。 – Benson 2011-03-01 09:22:16
实际上是nope,“reject”一次遍历数组,并且“collect”再次遍历数组,因此有两个迭代。在“每个”的情况下,它只做一次=) – Staelen 2011-03-01 09:27:27
这是一个合理的想法,但在Ruby中,进行速度测试并查看实际发生的事情通常非常有趣。在我的快速基准测试中(当然这可能与安德鲁的实际情况相匹配),以这种方式构建阵列的速度实际上是其他任何方式的两倍。我怀疑问题是在C中迭代数组实际上要比在Ruby <<级别追加项目要快得多。 – 2011-03-01 14:04:28
你可以拉决策变成一个辅助方法,并用它通过Enumerable#reduce
:
def potentially_keep(list, i)
if i === 3
list
else
list.push i
end
end
# => :potentially_keep
(1..4).reduce([]) { |memo, i| potentially_keep(memo, i) }
# => [1, 2, 4]
美丽的代码。这比我的解决方案好得多。 – Benson 2011-03-01 09:23:35
这是最慢的答案(虽然不是太多),但肯定是最干净的。我只是希望有一种方法可以用'collect'做到这一点,因为我期望调用'next'返回_absolutely nothing_,而不是“nothing”(又名'nil')。 – 2011-03-01 23:12:54
如果比其他任何方法都慢,那么Ruby的优化器可能会使用一些您认为没有用的工作? – Shannon 2012-12-27 21:30:00