source: EcnlProtoTool/trunk/mruby-2.1.1/mrblib/array.rb@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 6.1 KB
Line 
1# coding: utf-8
2##
3# Array
4#
5# ISO 15.2.12
6class Array
7
8 ##
9 # Calls the given block for each element of +self+
10 # and pass the respective element.
11 #
12 # ISO 15.2.12.5.10
13 # def each(&block)
14 # return to_enum :each unless block
15
16 # idx = 0
17 # while idx < length
18 # block.call(self[idx])
19 # idx += 1
20 # end
21 # self
22 # end
23
24 ##
25 # Calls the given block for each element of +self+
26 # and pass the index of the respective element.
27 #
28 # ISO 15.2.12.5.11
29 def each_index(&block)
30 return to_enum :each_index unless block
31
32 idx = 0
33 while idx < length
34 block.call(idx)
35 idx += 1
36 end
37 self
38 end
39
40 ##
41 # Calls the given block for each element of +self+
42 # and pass the respective element. Each element will
43 # be replaced by the resulting values.
44 #
45 # ISO 15.2.12.5.7
46 def collect!(&block)
47 return to_enum :collect! unless block
48
49 idx = 0
50 len = size
51 while idx < len
52 self[idx] = block.call self[idx]
53 idx += 1
54 end
55 self
56 end
57
58 ##
59 # Alias for collect!
60 #
61 # ISO 15.2.12.5.20
62 alias map! collect!
63
64 ##
65 # Private method for Array creation.
66 #
67 # ISO 15.2.12.5.15
68 def initialize(size=0, obj=nil, &block)
69 size = size.__to_int
70 raise ArgumentError, "negative array size" if size < 0
71
72 self.clear
73 if size > 0
74 self[size - 1] = nil # allocate
75
76 idx = 0
77 while idx < size
78 self[idx] = (block)? block.call(idx): obj
79 idx += 1
80 end
81 end
82
83 self
84 end
85
86 def _inspect(recur_list)
87 size = self.size
88 return "[]" if size == 0
89 return "[...]" if recur_list[self.object_id]
90 recur_list[self.object_id] = true
91 ary=[]
92 i=0
93 while i<size
94 ary<<self[i]._inspect(recur_list)
95 i+=1
96 end
97 "["+ary.join(", ")+"]"
98 end
99 ##
100 # Return the contents of this array as a string.
101 #
102 # ISO 15.2.12.5.31 (x)
103 def inspect
104 self._inspect({})
105 end
106 # ISO 15.2.12.5.32 (x)
107 alias to_s inspect
108
109 ##
110 # Equality---Two arrays are equal if they contain the same number
111 # of elements and if each element is equal to (according to
112 # Object.==) the corresponding element in the other array.
113 #
114 # ISO 15.2.12.5.33 (x)
115 def ==(other)
116 other = self.__ary_eq(other)
117 return false if other == false
118 return true if other == true
119 len = self.size
120 i = 0
121 while i < len
122 return false if self[i] != other[i]
123 i += 1
124 end
125 return true
126 end
127
128 ##
129 # Returns <code>true</code> if +self+ and _other_ are the same object,
130 # or are both arrays with the same content.
131 #
132 # ISO 15.2.12.5.34 (x)
133 def eql?(other)
134 other = self.__ary_eq(other)
135 return false if other == false
136 return true if other == true
137 len = self.size
138 i = 0
139 while i < len
140 return false unless self[i].eql?(other[i])
141 i += 1
142 end
143 return true
144 end
145
146 ##
147 # Comparison---Returns an integer (-1, 0, or +1)
148 # if this array is less than, equal to, or greater than <i>other_ary</i>.
149 # Each object in each array is compared (using <=>). If any value isn't
150 # equal, then that inequality is the return value. If all the
151 # values found are equal, then the return is based on a
152 # comparison of the array lengths. Thus, two arrays are
153 # "equal" according to <code>Array#<=></code> if and only if they have
154 # the same length and the value of each element is equal to the
155 # value of the corresponding element in the other array.
156 #
157 # ISO 15.2.12.5.36 (x)
158 def <=>(other)
159 other = self.__ary_cmp(other)
160 return 0 if 0 == other
161 return nil if nil == other
162
163 len = self.size
164 n = other.size
165 len = n if len > n
166 i = 0
167 while i < len
168 n = (self[i] <=> other[i])
169 return n if n.nil? || n != 0
170 i += 1
171 end
172 len = self.size - other.size
173 if len == 0
174 0
175 elsif len > 0
176 1
177 else
178 -1
179 end
180 end
181
182 ##
183 # Delete element with index +key+
184 def delete(key, &block)
185 while i = self.index(key)
186 self.delete_at(i)
187 ret = key
188 end
189 return block.call if ret.nil? && block
190 ret
191 end
192end
193
194##
195# Array is enumerable
196class Array
197 # ISO 15.2.12.3
198 include Enumerable
199
200 ##
201 # Sort all elements and replace +self+ with these
202 # elements.
203 def sort!(&block)
204 stack = [ [ 0, self.size - 1 ] ]
205 until stack.empty?
206 left, mid, right = stack.pop
207 if right == nil
208 right = mid
209 # sort self[left..right]
210 if left < right
211 if left + 1 == right
212 lval = self[left]
213 rval = self[right]
214 cmp = if block then block.call(lval,rval) else lval <=> rval end
215 if cmp.nil?
216 raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
217 end
218 if cmp > 0
219 self[left] = rval
220 self[right] = lval
221 end
222 else
223 mid = ((left + right + 1) / 2).floor
224 stack.push [ left, mid, right ]
225 stack.push [ mid, right ]
226 stack.push [ left, (mid - 1) ] if left < mid - 1
227 end
228 end
229 else
230 lary = self[left, mid - left]
231 lsize = lary.size
232
233 # The entity sharing between lary and self may cause a large memory
234 # copy operation in the merge loop below. This harmless operation
235 # cancels the sharing and provides a huge performance gain.
236 lary[0] = lary[0]
237
238 # merge
239 lidx = 0
240 ridx = mid
241 (left..right).each { |i|
242 if lidx >= lsize
243 break
244 elsif ridx > right
245 self[i, lsize - lidx] = lary[lidx, lsize - lidx]
246 break
247 else
248 lval = lary[lidx]
249 rval = self[ridx]
250 cmp = if block then block.call(lval,rval) else lval <=> rval end
251 if cmp.nil?
252 raise ArgumentError, "comparison of #{lval.inspect} and #{rval.inspect} failed"
253 end
254 if cmp <= 0
255 self[i] = lval
256 lidx += 1
257 else
258 self[i] = rval
259 ridx += 1
260 end
261 end
262 }
263 end
264 end
265 self
266 end
267
268 def sort(&block)
269 self.dup.sort!(&block)
270 end
271end
Note: See TracBrowser for help on using the repository browser.