unify the code for filter methods (and speed up #reject!)

the worst case for `Array#reject!` (i.e. a proc always returning `true`)
is at least 5x worse than the worst case for `Array#select!` (proc
always returning `false`)

this commit unifies these implementations and inlines the (effective)
call of `#select!` in `#keep_if` and `#reject!` in `#delete_if`
This commit is contained in:
leviongit
2024-04-13 08:53:25 +02:00
parent d761561be3
commit 81bb520919
+28 -26
View File
@@ -467,15 +467,16 @@ class Array
def delete_if(&block)
return to_enum :delete_if unless block
result = []
idx = 0
while idx < self.size do
if block.call(self[idx])
self.delete_at(idx)
else
idx += 1
end
len = size
while idx < len
elem = self[idx]
result << elem unless block.call(elem)
idx += 1
end
self
self.replace(result)
end
##
@@ -496,20 +497,18 @@ class Array
def reject!(&block)
return to_enum :reject! unless block
len = self.size
result = []
idx = 0
while idx < self.size do
if block.call(self[idx])
self.delete_at(idx)
else
idx += 1
end
end
if self.size == len
nil
else
self
len = size
while idx < len
elem = self[idx]
result << elem unless block.call(elem)
idx += 1
end
return nil if len == result.size
self.replace(result)
end
##
@@ -658,15 +657,16 @@ class Array
def keep_if(&block)
return to_enum :keep_if unless block
result = []
idx = 0
while idx < self.size do
if block.call(self[idx])
idx += 1
else
self.delete_at(idx)
end
len = size
while idx < len
elem = self[idx]
result << elem if block.call(elem)
idx += 1
end
self
self.replace(result)
end
##
@@ -694,7 +694,9 @@ class Array
result << elem if block.call(elem)
idx += 1
end
return nil if len == result.size
self.replace(result)
end