RubyFlow The Ruby and Rails community linklog

Rails 6 adds Array#including, Array#excluding, Enumerable#including, Enumerable#exclu

Rails 6 adds Array#including, Array#excluding, Enumerable#including, Enumerable#excluding as more readable approaches to collection additions and removals.

https://blog.saeloun.com/2019/03/05/rails-6-array-including-excluding.html

Comments

I really like the idea but the implementation does exactly the opposite of what I thought it was made for, which is to avoid intermediary array creation.

Imagine this:

``` require ‘benchmark/ips’

module Enumerable def excluding(without) if without.kind_of?(Array) to_a.each { |item| yield item unless without.include?(item) } else to_a.each { |item| yield item unless item == without } end end

def including(with, &block) to_a.each(&block) if with.kind_of?(Array) with.each(&block) else yield with end end end

arr1 = Array.new(999_999) { ‘a’ * rand(20) } arr1.insert(500_000, ‘b’)

Benchmark.ips do |x| x.report(‘excluding’) { arr1.excluding(‘b’) { |a| a } } x.report(‘-‘) { (arr1 - [‘b’]).each { |a| a } } end

Benchmark.ips do |x| x.report(‘including’) { arr1.including(‘c’) { |a| a } } x.report(‘+’) { (arr1 + [‘c’]).each { |a| a } } end ```

The result:

Warming up -------------------------------------- excluding 1.000 i/100ms - 1.000 i/100ms Calculating ------------------------------------- excluding 11.487 (± 0.0%) i/s - 58.000 in 5.051945s - 11.567 (±17.3%) i/s - 57.000 in 5.067871s Warming up -------------------------------------- including 2.000 i/100ms + 1.000 i/100ms Calculating ------------------------------------- including 24.601 (± 0.0%) i/s - 124.000 in 5.041172s + 21.230 (±14.1%) i/s - 102.000 in 5.034892s

(you could also do: ([1,2,3,4].to_enum + [5].to_enum).each { |i| puts i })

Ok so this comment system doesn’t suport the three backticks syntax. Reposting:

I really like the idea but the implementation does exactly the opposite of what I thought it was made for, which is to avoid intermediary array creation.

Imagine this:

require 'benchmark/ips'

module Enumerable
  def excluding(without)
    if without.kind_of?(Array)
      to_a.each { |item| yield item unless without.include?(item) }
    else
      to_a.each { |item| yield item unless item == without }
    end
  end

  def including(with, &block)
    to_a.each(&block)
    if with.kind_of?(Array)
      with.each(&block)
    else
      yield with
    end
  end
end

arr1 = Array.new(999_999) { 'a' * rand(20) }
arr1.insert(500_000, 'b')

Benchmark.ips do |x|
  x.report('excluding') { arr1.excluding('b') { |a| a } }
  x.report('-') { (arr1 - ['b']).each { |a| a } }
end

Benchmark.ips do |x|
  x.report('including') { arr1.including('c') { |a| a } }
  x.report('+') { (arr1 + ['c']).each { |a| a } }
end

The result:

Warming up --------------------------------------
           excluding     1.000  i/100ms
                   -     1.000  i/100ms
Calculating -------------------------------------
           excluding     11.487  (± 0.0%) i/s -     58.000  in   5.051945s
                   -     11.567  (±17.3%) i/s -     57.000  in   5.067871s
Warming up --------------------------------------
           including     2.000  i/100ms
                   +     1.000  i/100ms
Calculating -------------------------------------
           including     24.601  (± 0.0%) i/s -    124.000  in   5.041172s
                   +     21.230  (±14.1%) i/s -    102.000  in   5.034892s

You could also do:

 ([1,2,3,4].to_enum + [5].to_enum).each { |i| puts i })

since enums support chaining nowadays.

Post a comment

You can use basic HTML markup (e.g. <a>) or Markdown.

As you are not logged in, you will be
directed via GitHub to signup or sign in