From 81bb520919e7217985cdff7b367424a1487dfa6c Mon Sep 17 00:00:00 2001 From: leviongit Date: Sat, 13 Apr 2024 08:53:25 +0200 Subject: [PATCH] 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` --- mrbgems/mruby-array-ext/mrblib/array.rb | 54 +++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 7a9a0ac08..1339fc19b 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -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