⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynimic_base_index.rb

📁 二叉树详细源码
💻 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 + -