Merge pull request #1253 from skandhas/pr-add-comments-for-array-ext
[mruby.git] / mrbgems / mruby-array-ext / mrblib / array.rb
blob337cef632a2d38d1135ddb618df83fbac5817818
1 class Array
2   ##
3   # call-seq:
4   #    ary.uniq! -> ary or nil
5   #
6   # Removes duplicate elements from +self+.
7   # Returns <code>nil</code> if no changes are made (that is, no
8   # duplicates are found).
9   #
10   #    a = [ "a", "a", "b", "b", "c" ]
11   #    a.uniq!   #=> ["a", "b", "c"]
12   #    b = [ "a", "b", "c" ]
13   #    b.uniq!   #=> nil
14   #
15   def uniq!
16     ary = self.dup
17     result = []
18     while ary.size > 0
19       result << ary.shift
20       ary.delete(result.last)
21     end
22     if result.size == self.size
23       nil
24     else
25       self.replace(result)
26     end
27   end
29   ##
30   # call-seq:
31   #    ary.uniq   -> new_ary
32   #
33   # Returns a new array by removing duplicate values in +self+.
34   #
35   #    a = [ "a", "a", "b", "b", "c" ]
36   #    a.uniq   #=> ["a", "b", "c"]
37   #
38   def uniq
39     ary = self.dup
40     ary.uniq!
41     ary
42   end
44   ##
45   # call-seq:
46   #    ary - other_ary    -> new_ary
47   #
48   # Array Difference---Returns a new array that is a copy of
49   # the original array, removing any items that also appear in
50   # <i>other_ary</i>. (If you need set-like behavior, see the
51   # library class Set.)
52   #
53   #    [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
54   #
55   def -(elem)
56     raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
58     hash = {}
59     array = []
60     elem.each { |x| hash[x] = true }
61     self.each { |x| array << x unless hash[x] }
62     array
63   end
65   ##
66   # call-seq:
67   #    ary | other_ary     -> new_ary
68   #
69   # Set Union---Returns a new array by joining this array with
70   # <i>other_ary</i>, removing duplicates.
71   #
72   #    [ "a", "b", "c" ] | [ "c", "d", "a" ]
73   #           #=> [ "a", "b", "c", "d" ]
74   #
75   def |(elem)
76     raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
78     ary = self + elem
79     ary.uniq! or ary
80   end
82   ##
83   # call-seq:
84   #    ary & other_ary      -> new_ary
85   #
86   # Set Intersection---Returns a new array
87   # containing elements common to the two arrays, with no duplicates.
88   #
89   #    [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]
90   #
91   def &(elem)
92     raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
94     hash = {}
95     array = []
96     elem.each{|v| hash[v] = true }
97     self.each do |v|
98       if hash[v]
99         array << v
100         hash.delete v
101       end
102     end
103     array
104   end
106   ##
107   # call-seq:
108   #    ary.flatten -> new_ary
109   #    ary.flatten(level) -> new_ary
110   #
111   # Returns a new array that is a one-dimensional flattening of this
112   # array (recursively). That is, for every element that is an array,
113   # extract its elements into the new array.  If the optional
114   # <i>level</i> argument determines the level of recursion to flatten.
115   #
116   #    s = [ 1, 2, 3 ]           #=> [1, 2, 3]
117   #    t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
118   #    a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
119   #    a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
120   #    a = [ 1, 2, [3, [4, 5] ] ]
121   #    a.flatten(1)              #=> [1, 2, 3, [4, 5]]
122   #
123   def flatten(depth=nil)
124     ar = []
125     self.each do |e|
126       if e.is_a?(Array) && (depth.nil? || depth > 0)
127         ar += e.flatten(depth.nil? ? nil : depth - 1)
128       else
129         ar << e
130       end
131     end
132     ar
133   end
135   ##
136   # call-seq:
137   #    ary.flatten!        -> ary or nil
138   #    ary.flatten!(level) -> array or nil
139   #
140   # Flattens +self+ in place.
141   # Returns <code>nil</code> if no modifications were made (i.e.,
142   # <i>ary</i> contains no subarrays.)  If the optional <i>level</i>
143   # argument determines the level of recursion to flatten.
144   #
145   #    a = [ 1, 2, [3, [4, 5] ] ]
146   #    a.flatten!   #=> [1, 2, 3, 4, 5]
147   #    a.flatten!   #=> nil
148   #    a            #=> [1, 2, 3, 4, 5]
149   #    a = [ 1, 2, [3, [4, 5] ] ]
150   #    a.flatten!(1) #=> [1, 2, 3, [4, 5]]
151   #
152   def flatten!(depth=nil)
153     modified = false
154     ar = []
155     self.each do |e|
156       if e.is_a?(Array) && (depth.nil? || depth > 0)
157         ar += e.flatten(depth.nil? ? nil : depth - 1)
158         modified = true
159       else
160         ar << e
161       end
162     end
163     if modified
164       self.replace(ar)
165     else
166       nil
167     end
168   end
170   ##
171   # call-seq:
172   #    ary.compact     -> new_ary
173   #
174   # Returns a copy of +self+ with all +nil+ elements removed.
175   #
176   #    [ "a", nil, "b", nil, "c", nil ].compact
177   #                      #=> [ "a", "b", "c" ]
178   #
179   def compact
180     result = self.dup
181     result.compact!
182     result
183   end
185   ##
186   # call-seq:
187   #    ary.compact!    -> ary  or  nil
188   #
189   # Removes +nil+ elements from the array.
190   # Returns +nil+ if no changes were made, otherwise returns
191   # <i>ary</i>.
192   #
193   #    [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
194   #    [ "a", "b", "c" ].compact!           #=> nil
195   #
196   def compact!
197     result = self.select { |e| e != nil }
198     if result.size == self.size
199       nil
200     else
201       self.replace(result)
202     end
203   end