Skip to content

Instantly share code, notes, and snippets.

@pjambet
Created November 11, 2020 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pjambet/2edda31d280bfa2b98600dc9e263d5de to your computer and use it in GitHub Desktop.
Save pjambet/2edda31d280bfa2b98600dc9e263d5de to your computer and use it in GitHub Desktop.
A contrived sorted array
require 'forwardable'
module BYORedis
class SortedArray
extend Forwardable
def_delegators :@underlying, :[], :delete_if, :size, :each, :delete_at, :shift,
:bsearch_index, :map, :each_with_index, :pop
def initialize(*fields)
@underlying = []
@fields = fields.map(&:to_sym)
end
def push(new_element)
if @underlying.empty?
index = 0
else
index = @underlying.bsearch_index do |element|
comp = nil
count = 0
@fields.map do |field|
element_value = element.send(field)
new_element_value = new_element.send(field)
# p "comparing #{new_element_value}&#{element_value}"
if new_element_value == element_value
count += 1
next
elsif new_element_value < element_value
comp = true
break
else
comp = false
break
end
end
if count == @fields.size
p "ALL FIELDS EQUAL"
# all fields were equal
comp = true
end
comp
end
end
index = @underlying.size if index.nil?
@underlying.insert(index, new_element)
end
alias << push
def index(element)
if @underlying.empty?
nil
else
iter = 0
@underlying.bsearch_index do |x|
cmp = nil
# p "iter:#{iter}"
iter += 1
@fields.each do |field|
# Keep comparing as long as they're equal for 'field'
cmp = element.send(field) <=> x.send(field)
break unless cmp == 0
end
cmp
end
end
end
def delete(element)
# index = @underlying.bsearch_index { |x| x.send(@field) >= element.send(@field) }
index = index(element)
return if index.nil?
element_at_index = @underlying[index]
indices_for_deletion = []
while element_at_index
if element_at_index == element
indices_for_deletion << index
end
index += 1
next_element = @underlying[index]
if next_element && equal_for_fields(element, next_element)
element_at_index = next_element
else
break
end
end
indices_for_deletion.each { |i| @underlying.delete_at(i) }
end
private
def equal_for_fields(element1, element2)
@fields.all? do |field|
element1.send(field) == element2.send(field)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment