是否有合理的方法来执行以下操作:
我想获取一个数组,并根据条件从数组中选择特定项,然后将它们从数组中移除。 (我基本上想将数组的内容分成几类)。
array = [1,2,3,4,5,6,7,8]
less_than_three = array.reject_destructively{|v| v<3}
=> [1,2]
array
=> [3,4,5,6,7,8]
more_than_five = array.reject_destructively{|v| v>5}
=> [6,7,8]
array
=> [3,4,5]
我试过delete_if,选择!,拒绝!并且他们似乎都没有能够给你带来受影响的物品,而其余的则留下阵列。 除非我生气,这完全有可能。
答案 0 :(得分:5)
你可以为此建立自己的方法......
class Array
def extract(&block)
temp = self.select(&block)
self.reject!(&block)
temp
end
end
...然后
a = [1, 2, 3, 4, 5]
a.extract{|x| x < 3}
=> [1,2]
p a
=> [3, 4, 5]
编辑:如果你不想修补补丁(但猴子修补本身就不是邪恶的话),你可以用香草法做到这一点......
def select_from_array(array, &block)
temp = array.select(&block)
array.reject!(&block)
temp
end
array = [1,2,3,4,5,6,7,8]
less_than_three = select_from_array(array){|v| v<3}
=> [1,2]
array
=> [3,4,5,6,7,8]
more_than_five = select_from_array(array){|v| v>5}
=> [6,7,8]
array
=> [3,4,5]
答案 1 :(得分:3)
我理解这个问题,你不想生成两个新对象。你走了:
class Array
def carve!
dup.tap { delete_if &Proc.new } - self
end
end
array = [1,2,3,4,5,6,7,8]
p array.carve! { |v| v < 3 }
#⇒ [1, 2] # returned by Array#carve method
p array
#⇒ [3, 4, 5, 6, 7, 8] # remained in original array
使用此解决方案,array.__id__
保持不变。这是最高尔夫球的答案:)
答案 2 :(得分:1)
导轨6中有一种方法extract!
:
a = [1, 2, 3] #=> [1, 2, 3]
a.extract! { |num| num.odd? } #=> [1, 3]
a #=> [2]
答案 3 :(得分:0)
这会有帮助吗
class Array
def reject_destructively(&block)
arr = self.select(&block)
arr.each{ |i| self.delete(i) }
arr
end
end
array = [1,2,3,4,5,6,7,8]
p less_than_three = array.reject_destructively{|v| v<3}
#=> [1,2]
p array
#=> [3,4,5,6,7,8]
p more_than_five = array.reject_destructively{|v| v>5}
#=> [6,7,8]
p array
#=> [3,4,5]
以上代码可以进一步简化为:
class Array
def reject_destructively(&block)
self.select(&block).each{ |i| self.delete(i) }
end
end
答案 4 :(得分:0)
irb(main):001:0> array = [1,2,3,4,5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
irb(main):002:0> array.partition{|v| v < 3}
=> [[1, 2], [3, 4, 5, 6, 7, 8]]
是否有一个特定的原因,为什么必须destructive
?
答案 5 :(得分:0)
确定。这样可以避免猴子修补,将它保持在一条线......等等,但是它太丑了......
less_than_three = array.dup - array.reject!{|v| v<3}
=> [1,2]
array
=> [3,4,5,6,7,8]
more_than_five = array.dup - array.reject!{|v| v>5}
=> [6,7,8]
array
=> [3,4,5]
答案 6 :(得分:0)
module Enumerable
def reject_destructively
array=[]
self.each do |y|
if yield(y)
array<<y
end
end
array.each do |x|
self.delete(x)
end
return array
end
end
array=[10,9,2,1,3,45,52]
print less_than_three = array.reject_destructively{|v| v < 3}
print array
答案 7 :(得分:-1)
您可以使用group_by
获取满足条件的所有元素在一个组中,所有其余元素在另一个组中。
例如
[1,2,3,4,5].group_by{|i| i > 3}
给出
{false=>[1, 2, 3], true=>[4, 5]}
有关详情,请访问http://ruby-doc.org/core-2.1.1/Enumerable.html#method-i-group_by