+
+ ##
+ # call-seq:
+ # ary.delete_if { |item| block } -> ary
+ # ary.delete_if -> Enumerator
+ #
+ # Deletes every element of +self+ for which block evaluates to +true+.
+ #
+ # The array is changed instantly every time the block is called, not after
+ # the iteration is over.
+ #
+ # See also Array#reject!
+ #
+ # If no block is given, an Enumerator is returned instead.
+ #
+ # scores = [ 97, 42, 75 ]
+ # scores.delete_if {|score| score < 80 } #=> [97]
+
+ def delete_if(&block)
+ return to_enum :delete_if unless block_given?
+
+ idx = 0
+ len = self.size
+ while idx < self.size do
+ if block.call(self[idx])
+ self.delete_at(idx)
+ else
+ idx += 1
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.keep_if { |item| block } -> ary
+ # ary.keep_if -> Enumerator
+ #
+ # Deletes every element of +self+ for which the given block evaluates to
+ # +false+.
+ #
+ # See also Array#select!
+ #
+ # If no block is given, an Enumerator is returned instead.
+ #
+ # a = [1, 2, 3, 4, 5]
+ # a.keep_if { |val| val > 3 } #=> [4, 5]
+
+ def keep_if(&block)
+ return to_enum :keep_if unless block_given?
+
+ idx = 0
+ len = self.size
+ while idx < self.size do
+ if block.call(self[idx])
+ idx += 1
+ else
+ self.delete_at(idx)
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.select! {|item| block } -> ary or nil
+ # ary.select! -> Enumerator
+ #
+ # Invokes the given block passing in successive elements from +self+,
+ # deleting elements for which the block returns a +false+ value.
+ #
+ # If changes were made, it will return +self+, otherwise it returns +nil+.
+ #
+ # See also Array#keep_if
+ #
+ # If no block is given, an Enumerator is returned instead.
+
+ def select!(&block)
+ return to_enum :select! unless block_given?
+
+ idx = 0
+ len = self.size
+ while idx < self.size do
+ if block.call(self[idx])
+ idx += 1
+ else
+ self.delete_at(idx)
+ end
+ end
+ return nil if self.size == len
+ self
+ end