(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