4373b6a93fc17e9bc34ecce9df577ab72874ab69
[ruby.git] / array.rb
blob4373b6a93fc17e9bc34ecce9df577ab72874ab69
1 class Array
2   # call-seq:
3   #   shuffle!(random: Random) -> self
4   #
5   # Shuffles all elements in +self+ into a random order,
6   # as selected by the object given by the keyword argument +random+.
7   # Returns +self+:
8   #
9   #   a =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
10   #   a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
11   #   a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]
12   #
13   # Duplicate elements are included:
14   #
15   #   a =             [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
16   #   a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
17   #   a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
18   #
19   # The object given with the keyword argument +random+ is used as the random number generator.
20   #
21   # Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
22   def shuffle!(random: Random)
23     Primitive.rb_ary_shuffle_bang(random)
24   end
26   # call-seq:
27   #   shuffle(random: Random) -> new_array
28   #
29   # Returns a new array containing all elements from +self+ in a random order,
30   # as selected by the object given by the keyword argument +random+:
31   #
32   #   a =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
33   #   a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
34   #   a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3]
35   #
36   # Duplicate elements are included:
37   #
38   #   a =            [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
39   #   a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
40   #   a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]
41   #
42   # The object given with the keyword argument +random+ is used as the random number generator.
43   #
44   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
45   def shuffle(random: Random)
46     Primitive.rb_ary_shuffle(random)
47   end
49   # call-seq:
50   #   sample(random: Random) -> object
51   #   sample(count, random: Random) -> new_ary
52   #
53   # Returns random elements from +self+,
54   # as selected by the object given by the keyword argument +random+.
55   #
56   # With no argument +count+ given, returns one random element from +self+:
57   #
58   #   a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
59   #   a.sample # => 3
60   #   a.sample # => 8
61   #
62   # Returns +nil+ if +self+ is empty:
63   #
64   #   [].sample # => nil
65   #
66   # With a non-negative numeric argument +count+ given,
67   # returns a new array containing +count+ random elements from +self+:
68   #
69   #   a.sample(3) # => [8, 9, 2]
70   #   a.sample(6) # => [9, 6, 0, 3, 1, 4]
71   #
72   # The order of the result array is unrelated to the order of +self+.
73   #
74   # Returns a new empty +Array+ if +self+ is empty:
75   #
76   #   [].sample(4) # => []
77   #
78   # May return duplicates in +self+:
79   #
80   #   a = [1, 1, 1, 2, 2, 3]
81   #   a.sample(a.size) # => [1, 1, 3, 2, 1, 2]
82   #
83   # Returns no more than <tt>a.size</tt> elements
84   # (because no new duplicates are introduced):
85   #
86   #   a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7]
87   #
88   # The object given with the keyword argument +random+ is used as the random number generator:
89   #
90   #   a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
91   #   a.sample(random: Random.new(1))     # => 6
92   #   a.sample(4, random: Random.new(1))  # => [6, 10, 9, 2]
93   #
94   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
95   def sample(n = (ary = false), random: Random)
96     if Primitive.mandatory_only?
97       # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
98       Primitive.ary_sample0
99     else
100       # Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) }
101       Primitive.ary_sample(random, n, ary)
102     end
103   end
105   # call-seq:
106   #   first -> object or nil
107   #   first(count) -> new_array
108   #
109   # Returns elements from +self+, or +nil+; does not modify +self+.
110   #
111   # With no argument given, returns the first element (if available):
112   #
113   #   a = [:foo, 'bar', 2]
114   #   a.first # => :foo
115   #   a # => [:foo, "bar", 2]
116   #
117   # If +self+ is empty, returns +nil+.
118   #
119   #   [].first # => nil
120   #
121   # With a non-negative integer argument +count+ given,
122   # returns the first +count+ elements (as available) in a new array:
123   #
124   #   a.first(0)  # => []
125   #   a.first(2)  # => [:foo, "bar"]
126   #   a.first(50) # => [:foo, "bar", 2]
127   #
128   # Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
129   def first n = unspecified = true
130     if Primitive.mandatory_only?
131       Primitive.attr! :leaf
132       Primitive.cexpr! %q{ ary_first(self) }
133     else
134       if unspecified
135         Primitive.cexpr! %q{ ary_first(self) }
136       else
137         Primitive.cexpr! %q{  ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_FIRST) }
138       end
139     end
140   end
142   # call-seq:
143   #   last  -> last_object or nil
144   #   last(n) -> new_array
145   #
146   # Returns elements from +self+, or +nil+; +self+ is not modified.
147   #
148   # With no argument given, returns the last element, or +nil+ if +self+ is empty:
149   #
150   #   a = [:foo, 'bar', 2]
151   #   a.last # => 2
152   #   a # => [:foo, "bar", 2]
153   #   [].last # => nil
154   #
155   # With a non-negative integer argument +n+ given,
156   # returns a new array containing the trailing +n+ elements of +self+, as available:
157   #
158   #   a = [:foo, 'bar', 2]
159   #   a.last(2)  # => ["bar", 2]
160   #   a.last(50) # => [:foo, "bar", 2]
161   #   a.last(0)  # => []
162   #   [].last(3) # => []
163   #
164   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
165   def last n = unspecified = true
166     if Primitive.mandatory_only?
167       Primitive.attr! :leaf
168       Primitive.cexpr! %q{ ary_last(self) }
169     else
170       if unspecified
171         Primitive.cexpr! %q{ ary_last(self) }
172       else
173         Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_LAST) }
174       end
175     end
176   end
178   # call-seq:
179   #   fetch_values(*indexes) -> new_array
180   #   fetch_values(*indexes) { |index| ... } -> new_array
181   #
182   # With no block given, returns a new array containing the elements of +self+
183   # at the offsets specified by +indexes+. Each of the +indexes+ must be an
184   # {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]:
185   #
186   #    a = [:foo, :bar, :baz]
187   #    a.fetch_values(2, 0)   # => [:baz, :foo]
188   #    a.fetch_values(2.1, 0) # => [:baz, :foo]
189   #    a.fetch_values         # => []
190   #
191   # For a negative index, counts backwards from the end of the array:
192   #
193   #    a.fetch_values(-2, -1) # [:bar, :baz]
194   #
195   # When no block is given, raises an exception if any index is out of range.
196   #
197   # With a block given, for each index:
198   #
199   # - If the index is in range, uses an element of +self+ (as above).
200   # - Otherwise, calls the block with the index and uses the block's return value.
201   #
202   # Example:
203   #
204   #   a = [:foo, :bar, :baz]
205   #   a.fetch_values(1, 0, 42, 777) { |index| index.to_s }
206   #   # => [:bar, :foo, "42", "777"]
207   #
208   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
209   def fetch_values(*indexes, &block)
210     indexes.map! { |i| fetch(i, &block) }
211     indexes
212   end
214   with_yjit do
215     if Primitive.rb_builtin_basic_definition_p(:each)
216       undef :each
218       def each # :nodoc:
219         Primitive.attr! :inline_block, :c_trace
221         unless defined?(yield)
222           return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
223         end
224         _i = 0
225         value = nil
226         while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
227           yield value
228         end
229         self
230       end
231     end
233     if Primitive.rb_builtin_basic_definition_p(:map)
234       undef :map
236       def map # :nodoc:
237         Primitive.attr! :inline_block, :c_trace
239         unless defined?(yield)
240           return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
241         end
243         _i = 0
244         value = nil
245         result = Primitive.ary_sized_alloc
246         while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
247           result << yield(value)
248         end
249         result
250       end
252       if Primitive.rb_builtin_basic_definition_p(:collect)
253         undef :collect
254         alias collect map
255       end
256     end
258     if Primitive.rb_builtin_basic_definition_p(:select)
259       undef :select
261       def select # :nodoc:
262         Primitive.attr! :inline_block, :c_trace
264         unless defined?(yield)
265           return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
266         end
268         _i = 0
269         value = nil
270         result = Primitive.ary_sized_alloc
271         while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
272           result << value if yield value
273         end
274         result
275       end
277       if Primitive.rb_builtin_basic_definition_p(:filter)
278         undef :filter
279         alias filter select
280       end
281     end
282   end