mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
5bd63d6232
- use heap sort (O(1)) instead of merge sort (O(n)) for better space complexity. - method implemented in C for better performance As a result, simple sorting now consumes far less memory and is faster. Since it's implemented in C, fiber context switching is not allowed from comparison, but we consider the risk is minimal (no one switches context in the comparison, right?)
226 lines
4.7 KiB
Ruby
226 lines
4.7 KiB
Ruby
##
|
|
# Array
|
|
#
|
|
# ISO 15.2.12
|
|
class Array
|
|
##
|
|
# call-seq:
|
|
# array.each {|element| ... } -> self
|
|
# array.each -> Enumerator
|
|
#
|
|
# Calls the given block for each element of +self+
|
|
# and pass the respective element.
|
|
#
|
|
# ISO 15.2.12.5.10
|
|
def each(&block)
|
|
return to_enum :each unless block
|
|
|
|
idx = 0
|
|
while idx < length
|
|
block.call(self[idx])
|
|
idx += 1
|
|
end
|
|
self
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.each_index {|index| ... } -> self
|
|
# array.each_index -> Enumerator
|
|
#
|
|
# Calls the given block for each element of +self+
|
|
# and pass the index of the respective element.
|
|
#
|
|
# ISO 15.2.12.5.11
|
|
def each_index(&block)
|
|
return to_enum :each_index unless block
|
|
|
|
idx = 0
|
|
while idx < length
|
|
block.call(idx)
|
|
idx += 1
|
|
end
|
|
self
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.collect! {|element| ... } -> self
|
|
# array.collect! -> new_enumerator
|
|
#
|
|
# Calls the given block for each element of +self+
|
|
# and pass the respective element. Each element will
|
|
# be replaced by the resulting values.
|
|
#
|
|
# ISO 15.2.12.5.7
|
|
def collect!(&block)
|
|
return to_enum :collect! unless block
|
|
|
|
idx = 0
|
|
len = size
|
|
while idx < len
|
|
self[idx] = block.call self[idx]
|
|
idx += 1
|
|
end
|
|
self
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.map! {|element| ... } -> self
|
|
# array.map! -> new_enumerator
|
|
#
|
|
# Alias for collect!
|
|
#
|
|
# ISO 15.2.12.5.20
|
|
alias map! collect!
|
|
|
|
##
|
|
# Private method for Array creation.
|
|
#
|
|
# ISO 15.2.12.5.15
|
|
def initialize(size=0, obj=nil, &block)
|
|
if size.is_a?(Array) && obj==nil && block == nil
|
|
self.replace(size)
|
|
return self
|
|
end
|
|
size = size.__to_int
|
|
raise ArgumentError, "negative array size" if size < 0
|
|
|
|
self.clear
|
|
if size > 0
|
|
self[size - 1] = nil # allocate
|
|
|
|
idx = 0
|
|
while idx < size
|
|
self[idx] = (block)? block.call(idx): obj
|
|
idx += 1
|
|
end
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array == other -> true or false
|
|
#
|
|
# Equality---Two arrays are equal if they contain the same number
|
|
# of elements and if each element is equal to (according to
|
|
# Object.==) the corresponding element in the other array.
|
|
#
|
|
def ==(other)
|
|
other = self.__ary_eq(other)
|
|
return false if other == false
|
|
return true if other == true
|
|
len = self.size
|
|
i = 0
|
|
while i < len
|
|
return false if self[i] != other[i]
|
|
i += 1
|
|
end
|
|
return true
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.eql? other_array -> true or false
|
|
#
|
|
# Returns <code>true</code> if +self+ and _other_ are the same object,
|
|
# or are both arrays with the same content.
|
|
#
|
|
def eql?(other)
|
|
other = self.__ary_eq(other)
|
|
return false if other == false
|
|
return true if other == true
|
|
len = self.size
|
|
i = 0
|
|
while i < len
|
|
return false unless self[i].eql?(other[i])
|
|
i += 1
|
|
end
|
|
return true
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array <=> other_array -> -1, 0, or 1
|
|
#
|
|
# Comparison---Returns an integer (-1, 0, or +1)
|
|
# if this array is less than, equal to, or greater than <i>other_ary</i>.
|
|
# Each object in each array is compared (using <=>). If any value isn't
|
|
# equal, then that inequality is the return value. If all the
|
|
# values found are equal, then the return is based on a
|
|
# comparison of the array lengths. Thus, two arrays are
|
|
# "equal" according to <code>Array#<=></code> if and only if they have
|
|
# the same length and the value of each element is equal to the
|
|
# value of the corresponding element in the other array.
|
|
#
|
|
def <=>(other)
|
|
other = self.__ary_cmp(other)
|
|
return 0 if 0 == other
|
|
return nil if nil == other
|
|
|
|
len = self.size
|
|
n = other.size
|
|
len = n if len > n
|
|
i = 0
|
|
begin
|
|
while i < len
|
|
n = (self[i] <=> other[i])
|
|
return n if n.nil? || n != 0
|
|
i += 1
|
|
end
|
|
rescue NoMethodError
|
|
return nil
|
|
end
|
|
len = self.size - other.size
|
|
if len == 0
|
|
0
|
|
elsif len > 0
|
|
1
|
|
else
|
|
-1
|
|
end
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.delete(obj) -> deleted_object
|
|
# array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
|
|
#
|
|
# Delete element with index +key+
|
|
def delete(key, &block)
|
|
len = self.length
|
|
ret = self.__delete(key)
|
|
return block&.call(key) if len == self.length
|
|
|
|
ret
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.sort -> new_array
|
|
# array.sort {|a, b| ... } -> new_array
|
|
#
|
|
# Returns a new Array whose elements are those from +self+, sorted.
|
|
def sort(&block)
|
|
self.dup.sort!(&block)
|
|
end
|
|
|
|
##
|
|
# call-seq:
|
|
# array.to_a -> self
|
|
#
|
|
# Returns self, no need to convert.
|
|
def to_a
|
|
self
|
|
end
|
|
alias entries to_a
|
|
|
|
##
|
|
# Array is enumerable
|
|
# ISO 15.2.12.3
|
|
include Enumerable
|
|
end
|