📄 dynimic_base_index.rb
字号:
# Enhances Array to support any base index.
# It provides a property "base_index", indicates the current base index of the array object.
# The value of "base_index" influnces [] operator
# a = ['a','b','c','d','e']
# a.base_index #=> 0
# a[0] #=> 'a'
# a[1, 3] #=> ['b','c','d']
# a[1..4] #=> ['b','c','d','e']
# a[-1] #=> 'e'
#
# a.base_index = 1
# a[1] #=> 'a'
# a[1, 3] #=> ['a','b','c']
# a[1..4] #=> ['a','b','c','d']
# a[0] #=> 'e'
#
# and []= operator
# a = Array.new
# a.base_index = 1
# a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
# a[1, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
# a[2..3] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
# a[1, 2] = "?" #=> ["?", 2, nil, "4"]
# a[1..3] = "A" #=> ["A", "4"]
# a[0] = "Z" #=> ["A", "Z"]
# a[2..0] = nil #=> ["A"]
#
# and these functions:
# at()
# delete_at()
# each_index()
# fetch()
# fill()
# index()
# insert()
# rindex()
# slice()
# slice!()
# values_at()
# indexes()
# indices()
class Array
alias original_index_reader []
alias original_index_writer []=
alias original_at at
alias original_delete_at delete_at
alias original_each_index each_index
alias original_fetch fetch
alias original_fill fill
alias original_index index
alias original_insert insert
alias original_rindex rindex
alias original_slice slice
alias original_slice! slice!
alias original_values_at values_at
alias original_indexes indexes
alias original_indices indices
def base_index()
return defined?(@base_index)? @base_index : 0
end
def base_index=(value)
@base_index = value
end
def at(index)
return original_at(index - base_index)
end
def [](*args)
if args.length == 1 && args.original_at(0).is_a?(Fixnum) then # e.g. a[1]
return original_at(args.original_at(0)-base_index)
elsif args.length == 1 && args.original_at(0).is_a?(Range) then # e.g. a[1..3]
range = Range.new(args.original_at(0).begin-base_index,
args.original_at(0).end-base_index,
args.original_at(0).exclude_end?)
return original_index_reader(range)
elsif args.length == 2 then #e.g. a[1, 2]
return original_index_reader(args.original_at(0)-base_index,
args.original_at(1))
else
return original_index_reader(*args)
end
end
def []=(*args)
if args.length >= 2 then
if args.original_at(0).is_a?(Fixnum) then # e.g. a[1]='Y' or a[1,3] = 'Z' or a[1] = ['a','b'] or a[1..3] = ['a','b']
return original_index_writer(args.original_at(0)-base_index,
*args.original_index_reader(1..args.length-1))
elsif args.original_at(0).is_a?(Range) then # e.g. a[1..3] = 'Y' or a[1..3] = ['Y','Z']
range = Range.new(args.original_at(0).begin-base_index,
args.original_at(0).end-base_index,
args.original_at(0).exclude_end?)
return original_index_writer(range,
*args.original_index_reader(1..args.length-1))
end
end
end
def delete_at(index)
return original_delete_at(index - base_index)
end
def each_index
(0...self.length).each do |i|
yield(i+base_index)
end
return self
end
def fetch(*args)
if args.length == 1 # e.g. a.fetch(1) or a.fetch(1) { |value| value**2 }
if block_given?
return yield(self.original_at(args.original_at(0) - base_index))
else
return self.original_at(args.original_at(0) - base_index)
end
else # e.g. a.fetch(5, 'cat')
return original_fetch(args.original_at(0)-base_index,
*args.original_index_reader(1..args.length-1))
end
end
def fill(*args)
if block_given? then
if args.length == 0 then # e.g. a.fill {|i| i*i }
start_index = base_index
end_index = base_index + self.length - 1
elsif args.length == 1 && args.original_at(0).is_a?(Range)==false then #e.g. a.fill(2) {|i| i*i }
start_index = args.original_at(0)
end_index = base_index + self.length - 1
elsif args.length == 1 && args.original_at(0).is_a?(Range) then # e.g. a.fill(2..5) {|i| i*i }
start_index = args.original_at(0).begin
end_index = args.original_at(0).exclude_end?? args.original_at(0).end-1 : args.original_at(0).end
elsif args.length == 2 then # e.g. a.fill(2,2) {|i| i*i }
start_index = args.original_at(0)
end_index = start_index + args.original_at(1) - 1
else
original_fill(*args) # original_fill will raise exception :)
end
(start_index..end_index).each do |i|
self[i] = yield(i)
end
else
if args.length == 1 # e.g. a.fill('x')
obj = args.original_at(0)
start_index = base_index
end_index = base_index + self.length - 1
elsif args.length == 2 && args.original_at(1).is_a?(Range)==false # e.g. a.fill('x', 2)
obj = args.original_at(0)
start_index = args.original_at(1)
end_index = base_index + self.length - 1
elsif args.length == 2 && args.original_at(1).is_a?(Range) # e.g. a.fill('x', 2..5)
obj = args.original_at(0)
start_index = args.original_at(1).begin
end_index = args.original_at(1).exclude_end?? args.original_at(1).end-1 : args.original_at(1).end
elsif args.length == 3 # e.g. a.fill('x', 2, 2)
obj = args.original_at(0)
start_index = args.original_at(1)
end_index = start_index + args.original_at(2) - 1
else
original_fill(*args) # original_fill will raise exception :)
end
original_fill(obj, Range.new(start_index-base_index, end_index-base_index, false))
end
return self
end
def index(value)
result = original_index(value)
return result && (result + base_index)
end
def indexes(*args)
arguments = Array.new
args.each do |arg|
if arg.is_a?(Range)
range = Range.new(arg.begin-base_index,
arg.end-base_index,
arg.exclude_end?)
arguments << range
else
arguments << arg-base_index
end
end
return original_indexes(*arguments)
end
def indices(*args)
arguments = Array.new
args.each do |arg|
if arg.is_a?(Range)
range = Range.new(arg.begin-base_index,
arg.end-base_index,
arg.exclude_end?)
arguments << range
else
arguments << arg-base_index
end
end
return original_indices(*arguments)
end
def insert(*args)
if args.length >= 1
original_insert(args.original_at(0)-base_index,
*args.original_index_reader(1..args.length-1))
else
original_insert(*args) # original_insert will raise exception :)
end
end
def rindex(value)
result = original_rindex(value)
return result && (result + base_index)
end
def slice(*args)
return self[*args]
end
def slice!(*args)
result = self[*args]
delete_at(*args)
return result
end
def values_at(*args)
arguments = Array.new
args.each do |arg|
if arg.is_a?(Range)
range = Range.new(arg.begin-base_index,
arg.end-base_index,
arg.exclude_end?)
arguments << range
else
arguments << arg-base_index
end
end
return original_values_at(*arguments)
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -