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

Car*_*ela 2 ruby arrays

有没有明智的方法来做到以下几点:

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

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]
Run Code Online (Sandbox Code Playgroud)

我试过delete_if,选择!,拒绝!并且他们似乎都没有能够给你受影响的物品,而其余的则留下阵列.除非我生气,这完全有可能.

Ale*_*kin 6

据我了解的问题,您不想产生两个新对象。干得好:

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
Run Code Online (Sandbox Code Playgroud)

使用此解决方案,array.__id__保持不变。这是所有地方中最高尔夫的答案:)


Ste*_*zyn 5

你可以为此建立自己的方法......

class Array
  def extract(&block)
    temp = self.select(&block)
    self.reject!(&block)
    temp
  end
end
Run Code Online (Sandbox Code Playgroud)

然后...

a = [1, 2, 3, 4, 5]
a.extract{|x| x < 3}
=> [1,2]
p a
=> [3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

编辑:如果你不想猴子补丁(但猴子补丁本身并不邪恶)你可以用香草方法做...

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]
Run Code Online (Sandbox Code Playgroud)