2020-01-26 12:27:40 +03:00
|
|
|
class Array
|
|
|
|
# call-seq:
|
2024-10-15 21:33:59 +03:00
|
|
|
# shuffle!(random: Random) -> self
|
2020-01-26 12:27:40 +03:00
|
|
|
#
|
2024-10-15 21:33:59 +03:00
|
|
|
# Shuffles all elements in +self+ into a random order,
|
|
|
|
# as selected by the object given by keyword argument +random+;
|
|
|
|
# returns +self+:
|
2020-01-26 12:27:40 +03:00
|
|
|
#
|
2024-10-15 21:33:59 +03:00
|
|
|
# a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
# a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
|
|
|
|
# a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]
|
|
|
|
#
|
|
|
|
# Duplicate elements are included:
|
|
|
|
#
|
|
|
|
# a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
|
|
|
|
# a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
|
|
|
|
# a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
|
|
|
|
#
|
|
|
|
# The object given with keyword argument +random+ is used as the random number generator.
|
|
|
|
#
|
2024-10-15 22:35:03 +03:00
|
|
|
# Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
|
2020-01-26 12:27:40 +03:00
|
|
|
def shuffle!(random: Random)
|
2020-05-31 09:52:32 +03:00
|
|
|
Primitive.rb_ary_shuffle_bang(random)
|
2020-01-26 12:27:40 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
# call-seq:
|
2024-10-15 22:32:12 +03:00
|
|
|
# shuffle(random: Random) -> new_array
|
2020-01-26 12:27:40 +03:00
|
|
|
#
|
2024-10-15 22:32:12 +03:00
|
|
|
# Returns a new array containing all elements from +self+ in a random order,
|
|
|
|
# as selected by the object given by keyword argument +random+:
|
2020-01-26 12:27:40 +03:00
|
|
|
#
|
2024-10-15 22:32:12 +03:00
|
|
|
# a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
# a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
|
|
|
|
# a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3]
|
|
|
|
#
|
|
|
|
# Duplicate elements are included:
|
|
|
|
#
|
|
|
|
# a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
|
|
|
|
# a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
|
|
|
|
# a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]
|
|
|
|
#
|
|
|
|
# The object given with keyword argument +random+ is used as the random number generator.
|
|
|
|
#
|
|
|
|
# Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
|
2020-01-26 12:27:40 +03:00
|
|
|
def shuffle(random: Random)
|
2020-05-31 09:52:32 +03:00
|
|
|
Primitive.rb_ary_shuffle(random)
|
2020-01-26 12:27:40 +03:00
|
|
|
end
|
2020-01-26 12:34:18 +03:00
|
|
|
|
|
|
|
# call-seq:
|
2024-10-11 18:25:58 +03:00
|
|
|
# sample(random: Random) -> object
|
|
|
|
# sample(count, random: Random) -> new_ary
|
2020-09-02 22:02:34 +03:00
|
|
|
#
|
2024-10-11 18:25:58 +03:00
|
|
|
# Returns random elements from +self+,
|
|
|
|
# as selected by the object given by keyword argument +random+.
|
2020-09-02 22:02:34 +03:00
|
|
|
#
|
2024-10-11 18:25:58 +03:00
|
|
|
# With no argument +count+ given, returns one random element from +self+:
|
|
|
|
#
|
|
|
|
# a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
2020-09-02 22:02:34 +03:00
|
|
|
# a.sample # => 3
|
|
|
|
# a.sample # => 8
|
|
|
|
#
|
2024-10-11 18:25:58 +03:00
|
|
|
# Returns +nil+ if +self+ is empty:
|
|
|
|
#
|
|
|
|
# [].sample # => nil
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# With non-negative numeric argument +count+ given,
|
|
|
|
# returns a new array containing +count+ random elements from +self+:
|
|
|
|
#
|
2020-09-02 22:02:34 +03:00
|
|
|
# a.sample(3) # => [8, 9, 2]
|
2024-10-11 18:25:58 +03:00
|
|
|
# a.sample(6) # => [9, 6, 0, 3, 1, 4]
|
|
|
|
#
|
|
|
|
# The order of the result array is unrelated to the order of +self+.
|
|
|
|
#
|
|
|
|
# Returns a new empty +Array+ if +self+ is empty:
|
|
|
|
#
|
|
|
|
# [].sample(4) # => []
|
|
|
|
#
|
|
|
|
# May return duplicates in +self+:
|
|
|
|
#
|
|
|
|
# a = [1, 1, 1, 2, 2, 3]
|
|
|
|
# a.sample(a.size) # => [1, 1, 3, 2, 1, 2]
|
|
|
|
#
|
2020-09-02 22:02:34 +03:00
|
|
|
# Returns no more than <tt>a.size</tt> elements
|
|
|
|
# (because no new duplicates are introduced):
|
|
|
|
#
|
2024-10-11 18:25:58 +03:00
|
|
|
# a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7]
|
|
|
|
#
|
|
|
|
# The object given with keyword argument +random+ is used as the random number generator:
|
|
|
|
#
|
2020-09-02 22:02:34 +03:00
|
|
|
# a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
2020-01-26 12:34:18 +03:00
|
|
|
# a.sample(random: Random.new(1)) #=> 6
|
|
|
|
# a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
|
2024-10-11 18:25:58 +03:00
|
|
|
#
|
|
|
|
# Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
|
2020-01-26 12:34:18 +03:00
|
|
|
def sample(n = (ary = false), random: Random)
|
2021-11-12 20:15:09 +03:00
|
|
|
if Primitive.mandatory_only?
|
|
|
|
# Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
|
|
|
|
Primitive.ary_sample0
|
|
|
|
else
|
|
|
|
# Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) }
|
|
|
|
Primitive.ary_sample(random, n, ary)
|
|
|
|
end
|
2020-01-26 12:34:18 +03:00
|
|
|
end
|
2023-03-09 19:33:00 +03:00
|
|
|
|
2023-05-10 09:47:39 +03:00
|
|
|
# call-seq:
|
2024-09-30 04:21:55 +03:00
|
|
|
# first -> object or nil
|
|
|
|
# first(count) -> new_array
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-09-30 04:21:55 +03:00
|
|
|
# Returns elements from +self+, or +nil+; does not modify +self+.
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-09-30 04:21:55 +03:00
|
|
|
# With no argument given, returns the first element (if available):
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
|
|
|
# a = [:foo, 'bar', 2]
|
|
|
|
# a.first # => :foo
|
|
|
|
# a # => [:foo, "bar", 2]
|
|
|
|
#
|
|
|
|
# If +self+ is empty, returns +nil+.
|
|
|
|
#
|
2024-09-30 04:21:55 +03:00
|
|
|
# [].first # => nil
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-09-30 04:21:55 +03:00
|
|
|
# With non-negative integer argument +count+ given,
|
|
|
|
# returns the first +count+ elements (as available) in a new array:
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-09-30 04:21:55 +03:00
|
|
|
# a.first(0) # => []
|
|
|
|
# a.first(2) # => [:foo, "bar"]
|
2023-05-10 09:47:39 +03:00
|
|
|
# a.first(50) # => [:foo, "bar", 2]
|
|
|
|
#
|
2024-09-30 04:21:55 +03:00
|
|
|
# Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
|
2023-03-09 19:33:00 +03:00
|
|
|
def first n = unspecified = true
|
|
|
|
if Primitive.mandatory_only?
|
|
|
|
Primitive.attr! :leaf
|
|
|
|
Primitive.cexpr! %q{ ary_first(self) }
|
|
|
|
else
|
|
|
|
if unspecified
|
|
|
|
Primitive.cexpr! %q{ ary_first(self) }
|
|
|
|
else
|
|
|
|
Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_FIRST) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-05-10 09:47:39 +03:00
|
|
|
# call-seq:
|
2024-10-02 17:55:19 +03:00
|
|
|
# last -> last_object or nil
|
|
|
|
# last(n) -> new_array
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-10-02 17:55:19 +03:00
|
|
|
# Returns elements from +self+, or +nil+; +self+ is not modified.
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-10-02 17:55:19 +03:00
|
|
|
# With no argument given, returns the last element, or +nil+ if +self+ is empty:
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
|
|
|
# a = [:foo, 'bar', 2]
|
|
|
|
# a.last # => 2
|
|
|
|
# a # => [:foo, "bar", 2]
|
2024-10-02 17:55:19 +03:00
|
|
|
# [].last # => nil
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
|
|
|
#
|
2024-10-02 17:55:19 +03:00
|
|
|
# With non-negative integer argument +n+ is given,
|
|
|
|
# returns a new array containing the trailing +n+ elements of +self+, as available:
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
|
|
|
# a = [:foo, 'bar', 2]
|
2024-10-02 17:55:19 +03:00
|
|
|
# a.last(2) # => ["bar", 2]
|
2023-05-10 09:47:39 +03:00
|
|
|
# a.last(50) # => [:foo, "bar", 2]
|
2024-10-02 17:55:19 +03:00
|
|
|
# a.last(0) # => []
|
|
|
|
# [].last(3) # => []
|
2023-05-10 09:47:39 +03:00
|
|
|
#
|
2024-10-02 17:55:19 +03:00
|
|
|
# Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
|
2023-03-09 19:33:00 +03:00
|
|
|
def last n = unspecified = true
|
|
|
|
if Primitive.mandatory_only?
|
|
|
|
Primitive.attr! :leaf
|
|
|
|
Primitive.cexpr! %q{ ary_last(self) }
|
|
|
|
else
|
|
|
|
if unspecified
|
|
|
|
Primitive.cexpr! %q{ ary_last(self) }
|
|
|
|
else
|
|
|
|
Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_LAST) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2024-09-05 21:00:32 +03:00
|
|
|
|
|
|
|
# call-seq:
|
2024-09-12 22:19:20 +03:00
|
|
|
# fetch_values(*indexes) -> new_array
|
|
|
|
# fetch_values(*indexes) {|index| ... } -> new_array
|
|
|
|
#
|
|
|
|
# With no block given, returns a new array containing the elements of +self+
|
|
|
|
# at the offsets given by +indexes+;
|
|
|
|
# each of the +indexes+ must be an
|
|
|
|
# {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]:
|
2024-09-05 21:00:32 +03:00
|
|
|
#
|
|
|
|
# a = [:foo, :bar, :baz]
|
2024-09-12 22:19:20 +03:00
|
|
|
# a.fetch_values(3, 1) # => [:baz, :foo]
|
|
|
|
# a.fetch_values(3.1, 1) # => [:baz, :foo]
|
|
|
|
# a.fetch_values # => []
|
|
|
|
#
|
|
|
|
# For a negative index, counts backwards from the end of the array:
|
|
|
|
#
|
|
|
|
# a.fetch_values([-2, -1]) # [:bar, :baz]
|
|
|
|
#
|
|
|
|
# When no block is given, raises an exception if any index is out of range.
|
|
|
|
#
|
|
|
|
# With a block given, for each index:
|
|
|
|
#
|
|
|
|
# - If the index in in range, uses an element of +self+ (as above).
|
|
|
|
# - Otherwise calls, the block with the index, and uses the block's return value.
|
2024-09-05 21:00:32 +03:00
|
|
|
#
|
2024-09-12 22:19:20 +03:00
|
|
|
# Example:
|
2024-09-05 21:00:32 +03:00
|
|
|
#
|
|
|
|
# a = [:foo, :bar, :baz]
|
2024-09-12 22:19:20 +03:00
|
|
|
# a.fetch_values(1, 0, 42, 777) {|index| index.to_s}
|
|
|
|
# # => [:bar, :foo, "42", "777"]
|
2024-09-05 21:00:32 +03:00
|
|
|
#
|
2024-09-12 22:19:20 +03:00
|
|
|
# Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
|
2024-09-05 21:00:32 +03:00
|
|
|
def fetch_values(*indexes, &block)
|
|
|
|
indexes.map! { |i| fetch(i, &block) }
|
|
|
|
indexes
|
|
|
|
end
|
2024-11-04 19:14:28 +03:00
|
|
|
|
|
|
|
with_yjit do
|
|
|
|
if Primitive.rb_builtin_basic_definition_p(:each)
|
|
|
|
undef :each
|
|
|
|
|
|
|
|
def each # :nodoc:
|
|
|
|
Primitive.attr! :inline_block, :c_trace
|
|
|
|
|
|
|
|
unless defined?(yield)
|
|
|
|
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
|
|
|
|
end
|
|
|
|
_i = 0
|
|
|
|
value = nil
|
|
|
|
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
|
|
|
|
yield value
|
|
|
|
end
|
|
|
|
self
|
|
|
|
end
|
|
|
|
end
|
2024-11-13 07:39:32 +03:00
|
|
|
|
2024-11-13 07:47:48 +03:00
|
|
|
if Primitive.rb_builtin_basic_definition_p(:map)
|
|
|
|
undef :map
|
|
|
|
|
|
|
|
def map # :nodoc:
|
|
|
|
Primitive.attr! :inline_block, :c_trace
|
|
|
|
|
|
|
|
unless defined?(yield)
|
|
|
|
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
|
|
|
|
end
|
|
|
|
|
|
|
|
_i = 0
|
|
|
|
value = nil
|
|
|
|
result = Primitive.ary_sized_alloc
|
|
|
|
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
|
|
|
|
result << yield(value)
|
|
|
|
end
|
|
|
|
result
|
|
|
|
end
|
|
|
|
|
|
|
|
if Primitive.rb_builtin_basic_definition_p(:collect)
|
|
|
|
undef :collect
|
|
|
|
alias collect map
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-11-13 07:39:32 +03:00
|
|
|
if Primitive.rb_builtin_basic_definition_p(:select)
|
|
|
|
undef :select
|
|
|
|
|
|
|
|
def select # :nodoc:
|
|
|
|
Primitive.attr! :inline_block, :c_trace
|
|
|
|
|
|
|
|
unless defined?(yield)
|
|
|
|
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
|
|
|
|
end
|
|
|
|
|
|
|
|
_i = 0
|
|
|
|
value = nil
|
|
|
|
result = Primitive.ary_sized_alloc
|
|
|
|
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
|
|
|
|
result << value if yield value
|
|
|
|
end
|
|
|
|
result
|
|
|
|
end
|
|
|
|
|
|
|
|
if Primitive.rb_builtin_basic_definition_p(:filter)
|
|
|
|
undef :filter
|
|
|
|
alias filter select
|
|
|
|
end
|
|
|
|
end
|
2024-11-04 19:14:28 +03:00
|
|
|
end
|
2020-01-26 12:27:40 +03:00
|
|
|
end
|