在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
A[1] / \ A[2] A[3] / \ / \ A[4] A[5] A[6] A[7] / \ A[8] A[9] 正如您所看到的,要求数组的起始下标为1才方便。可是Ruby的数组的起始下标是0。我们的想法是为Ruby的Array增加一个属性“base_index”属性,用它来获取或设置数组的起始下标。先看一下完成后的效果吧:
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' 本来以为只要重新定义Array的[]和[]=操作符就行了,后来发现原来有n多函数需要重新定义呀!全部的实现代码如下(文件名:“dynimic_base_index.rb”)
1# Enhances Array to support any base index. 2# It provides a property "base_index", indicates the current base index of the array object. 3# The value of "base_index" influnces [] operator 4# a = ['a','b','c','d','e'] 5# a.base_index #=> 0 6# a[0] #=> 'a' 7# a[1, 3] #=> ['b','c','d'] 8# a[1..4] #=> ['b','c','d','e'] 9# a[-1] #=> 'e' 10# 11# a.base_index = 1 12# a[1] #=> 'a' 13# a[1, 3] #=> ['a','b','c'] 14# a[1..4] #=> ['a','b','c','d'] 15# a[0] #=> 'e' 16# 17# and []= operator 18# a = Array.new 19# a.base_index = 1 20# a[4] = "4"; #=> [nil, nil, nil, nil, "4"] 21# a[1, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"] 22# a[2..3] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"] 23# a[1, 2] = "?" #=> ["?", 2, nil, "4"] 24# a[1..3] = "A" #=> ["A", "4"] 25# a[0] = "Z" #=> ["A", "Z"] 26# a[2..0] = nil #=> ["A"] 27# 28# and these functions: 29# at() 30# delete_at() 31# each_index() 32# fetch() 33# fill() 34# index() 35# insert() 36# rindex() 37# slice() 38# slice!() 39# values_at() 40# indexes() 41# indices() 42class Array 43 alias original_index_reader [] 44 alias original_index_writer []= 45 alias original_at at 46 alias original_delete_at delete_at 47 alias original_each_index each_index 48 alias original_fetch fetch 49 alias original_fill fill 50 alias original_index index 51 alias original_insert insert 52 alias original_rindex rindex 53 alias original_slice slice 54 alias original_slice! slice! 55 alias original_values_at values_at 56 alias original_indexes indexes 57 alias original_indices indices 58 59 def base_index() 60 return defined?(@base_index)? @base_index : 0 61 end 62 63 def base_index=(value) 64 @base_index = value 65 end 66 67 def at(index) 68 return original_at(index - base_index) 69 end 70 71 def [](*args) 72 if args.length == 1 && args.original_at(0).is_a?(Fixnum) then # e.g. a[1] 73 return original_at(args.original_at(0)-base_index) 74 elsif args.length == 1 && args.original_at(0).is_a?(Range) then # e.g. a[1..3] 75 range = Range.new(args.original_at(0).begin-base_index, 76 args.original_at(0).end-base_index, 77 args.original_at(0).exclude_end?) 78 return original_index_reader(range) 79 elsif args.length == 2 then #e.g. a[1, 2] 80 return original_index_reader(args.original_at(0)-base_index, 81 args.original_at(1)) 82 else 83 return original_index_reader(*args) 84 end 85 end 86 87 def []=(*args) 88 if args.length >= 2 then 89 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'] 90 return original_index_writer(args.original_at(0)-base_index, 91 *args.original_index_reader(1..args.length-1)) 92 elsif args.original_at(0).is_a?(Range) then # e.g. a[1..3] = 'Y' or a[1..3] = ['Y','Z'] 93 range = Range.new(args.original_at(0).begin-base_index, 94 args.original_at(0).end-base_index, 95 args.original_at(0).exclude_end?) 96 return original_index_writer(range, 97 *args.original_index_reader(1..args.length-1)) 98 end 99 end 100 end 101 102 def delete_at(index) 103 return original_delete_at(index - base_index) 104 end 105 106 def each_index 107 (0self.length).each do |i| 108 yield(i+base_index) 109 end 110 111 return self 112 end 113 114 def fetch(*args) 115 if args.length == 1 # e.g. a.fetch(1) or a.fetch(1) { |value| value**2 } 116 if block_given? 117 return yield(self.original_at(args.original_at(0) - base_index)) 118 else 119 return self.original_at(args.original_at(0) - base_index) 120 end 121 else # e.g. a.fetch(5, 'cat') 122 return original_fetch(args.original_at(0)-base_index, 123 *args.original_index_reader(1..args.length-1)) 124 end 125 end 126 127 def fill(*args) 128 if block_given? then 129 if args.length == 0 then # e.g. a.fill {|i| i*i } 130 start_index = base_index 131 end_index = base_index + self.length - 1 132 elsif args.length == 1 && args.original_at(0).is_a?(Range)==false then #e.g. a.fill(2) {|i| i*i } 133 start_index = args.original_at(0) 134 end_index = base_index + self.length - 1 135 elsif args.length == 1 && args.original_at(0).is_a?(Range) then # e.g. a.fill(2..5) {|i| i*i } 136 start_index = args.original_at(0).begin 137 end_index = args.original_at(0).exclude_end?? args.original_at(0).end-1 : args.original_at(0).end 138 elsif args.length == 2 then # e.g. a.fill(2,2) {|i| i*i } 139 start_index = args.original_at(0) 140 end_index = start_index + args.original_at(1) - 1 141 else 142 original_fill(*args) # original_fill will raise exception :) 143 end 144 (start_index..end_index).each do |i| 145 self[i] = yield(i) 146 end 147 else 148 if args.length == 1 # e.g. a.fill('x') 149 obj = args.original_at(0) 150 start_index = base_index 151 end_index = base_index + self.length - 1 152 elsif args.length == 2 && args.original_at(1).is_a?(Range)==false # e.g. a.fill('x', 2) 153 obj = args.original_at(0) 154 start_index = args.original_at(1) 155 end_index = base_index + self.length - 1 156 elsif args.length == 2 && args.original_at(1).is_a?(Range) # e.g. a.fill('x', 2..5) 157 obj = args.original_at(0) 158 start_index = args.original_at(1).begin 159 end_index = args.original_at(1).exclude_end?? args.original_at(1).end-1 : args.original_at(1).end 160 elsif args.length == 3 # e.g. a.fill('x', 2, 2) 161 obj = args.original_at(0) 162 start_index = args.original_at(1) 163 end_index = start_index + args.original_at(2) - 1 164 else 165 original_fill(*args) # original_fill will raise exception :) 166 end 167 original_fill(obj, Range.new(start_index-base_index, end_index-base_index, false)) 168 end 169 170 return self 171 end 172 173 def index(value) 174 result = original_index(value) 175 return result && (result + base_index) 176 end 177 178 def indexes(*args) 179 arguments = Array.new 180 181 args.each do |arg| 182 if arg.is_a?(Range) 183 range = Range.new(arg.begin-base_index, 184 arg.end-base_index, 185 arg.exclude_end?) 186 arguments << range 187 else 188 arguments << arg-base_index 189 end 190 end 191 192 return original_indexes(*arguments) 193 end 194 195 def indices(*args) 196 arguments = Array.new 197 198 args.each do |arg| 199 if arg.is_a?(Range) 200 range = Range.new(arg.begin-base_index, 201 arg.end-base_index, 202 arg.exclude_end?) 203 arguments << range 204 else 205 arguments << arg-base_index 206 end 207 end 208 209 return original_indices(*arguments) 210 end 211 212 def insert(*args) 213 if args.length >= 1 214 original_insert(args.original_at(0)-base_index, 215 *args.original_index_reader(1..args.length-1)) 216 else 217 original_insert(*args) # original_insert will raise exception :) 218 end 219 end 220 221 def rindex(value) 222 result = original_rindex(value) 223 return result && (result + base_index) 224 end 225 226 def slice(*args) 227 return self[ |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论