Created
November 11, 2020 20:53
-
-
Save pjambet/2edda31d280bfa2b98600dc9e263d5de to your computer and use it in GitHub Desktop.
A contrived sorted array
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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