Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save lucianghinda/6016e7bb0fce4425d49182b26712ccb9 to your computer and use it in GitHub Desktop.

Select an option

Save lucianghinda/6016e7bb0fce4425d49182b26712ccb9 to your computer and use it in GitHub Desktop.
3 New RuboCop Style Cops: SelectByKind, SelectByRange, PartitionInsteadOfDoubleSelect
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'benchmark/ips'
ITEMS = 400_000
ITERATIONS = 60
DATASET = Array.new(ITEMS) { rand(-1_000..1_000) }.freeze
def assert_same!(left, right, label)
raise "Mismatch for #{label}" unless left == right
end
positives_select = DATASET.select(&:positive?)
non_positives_reject = DATASET.reject(&:positive?)
positives_partition, non_positives_partition = DATASET.partition(&:positive?)
assert_same!(positives_select, positives_partition, 'positive bucket')
assert_same!(non_positives_reject, non_positives_partition, 'non-positive bucket')
puts "Dataset size: #{DATASET.size}"
puts "Positives: #{positives_partition.size}"
puts "Non-positives: #{non_positives_partition.size}"
puts
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('select + reject (two traversals)') do
ITERATIONS.times do
positives = DATASET.select(&:positive?)
negatives = DATASET.reject(&:positive?)
[positives, negatives]
end
end
x.report('partition (single traversal)') do
ITERATIONS.times { DATASET.partition(&:positive?) }
end
x.compare!
end
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'benchmark/ips'
class BaseRecord
end
class UserRecord < BaseRecord
end
class AdminRecord < UserRecord
end
class GuestRecord < BaseRecord
end
ITEMS = 200_000
ITERATIONS = 40
DATASET = Array.new(ITEMS) do |i|
case i % 4
when 0 then UserRecord.new
when 1 then AdminRecord.new
when 2 then GuestRecord.new
else i
end
end.freeze
def assert_same!(left, right, label)
raise "Mismatch for #{label}" unless left == right
end
select_result = DATASET.select { |x| x.is_a?(UserRecord) }
grep_result = DATASET.grep(UserRecord)
assert_same!(select_result, grep_result, 'select vs grep')
reject_result = DATASET.reject { |x| x.is_a?(UserRecord) }
grep_v_result = DATASET.grep_v(UserRecord)
assert_same!(reject_result, grep_v_result, 'reject vs grep_v')
puts "Dataset size: #{DATASET.size}"
puts "Matches for UserRecord: #{grep_result.size}"
puts
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('select { is_a?(UserRecord) }') do
ITERATIONS.times { DATASET.select { |item| item.is_a?(UserRecord) } }
end
x.report('grep(UserRecord)') do
ITERATIONS.times { DATASET.grep(UserRecord) }
end
x.report('reject { is_a?(UserRecord) }') do
ITERATIONS.times { DATASET.reject { |item| item.is_a?(UserRecord) } }
end
x.report('grep_v(UserRecord)') do
ITERATIONS.times { DATASET.grep_v(UserRecord) }
end
x.compare!
end
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'benchmark/ips'
ITEMS = 300_000
ITERATIONS = 45
TARGET_RANGE = (50..150)
DATASET = Array.new(ITEMS) { rand(1..200) }.freeze
def assert_same!(left, right, label)
raise "Mismatch for #{label}" unless left == right
end
select_cover = DATASET.select { |x| TARGET_RANGE.cover?(x) }
grep_cover = DATASET.grep(TARGET_RANGE)
assert_same!(select_cover, grep_cover, 'cover? vs grep')
reject_cover = DATASET.reject { |x| TARGET_RANGE.cover?(x) }
grep_v_cover = DATASET.grep_v(TARGET_RANGE)
assert_same!(reject_cover, grep_v_cover, 'reject cover? vs grep_v')
puts "Dataset size: #{DATASET.size}"
puts "Range: #{TARGET_RANGE}"
puts "Matches: #{grep_cover.size}"
puts
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('select { range.cover?(x) }') do
ITERATIONS.times { DATASET.select { |item| TARGET_RANGE.cover?(item) } }
end
x.report('grep(range)') do
ITERATIONS.times { DATASET.grep(TARGET_RANGE) }
end
x.report('reject { range.cover?(x) }') do
ITERATIONS.times { DATASET.reject { |item| TARGET_RANGE.cover?(item) } }
end
x.report('grep_v(range)') do
ITERATIONS.times { DATASET.grep_v(TARGET_RANGE) }
end
x.compare!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment