来自数组的破坏性拒绝返回拒绝的值

时间:2015-08-28 14:30:58

标签: arrays ruby

是否有合理的方法来执行以下操作:

我想获取一个数组,并根据条件从数组中选择特定项,然后将它们从数组中移除。 (我基本上想将数组的内容分成几类)。

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,选择!,拒绝!并且他们似乎都没有能够给你带来受影响的物品,而其余的则留下阵列。 除非我生气,这完全有可能。

8 个答案:

答案 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