class KXI::Collections::Enumerable

Allows it's superclass to be enumerated @note Order of items is not guaranteed @abstract

Public Class Methods

new() click to toggle source

Instantiates the {KXI::Collections::Enumerable} class

# File lib/kxi/collections/enumerable.rb, line 10
def initialize
        @locks = 0
        @alter = false
end

Public Instance Methods

aggregate(start = nil) { |start, item| ... } click to toggle source

Aggregates all items of collection @param start [Object, nil] Starting value @return [Object] Aggregated value @yield [current, item] Aggregation function @yieldparam current [Object] Current aggregate @yieldparam item [Object] Item of collection @yieldreturn [Object] Aggregated value

# File lib/kxi/collections/enumerable.rb, line 315
def aggregate(start = nil)
        foreach do |item|
                start = yield(start, item)
        end
        return start
end
all() { |item| ... } click to toggle source

Checks if all items in collection satisfy given function @return [Bool] True if all items of collection satisfy given function; otherwise false @yield [item] Function used for checking @yieldparam item [Object] Item of collection @yieldreturn [Bool] True if item satisfies given function; otherwise false

# File lib/kxi/collections/enumerable.rb, line 158
def all
        foreach do |item|
                return false unless yield(item)
        end
        return true
end
any() { |item| ... } click to toggle source

Checks if collection contains any item @return [Bool] True if collection contains any item; otherwise false @overload any()

Checks if collection is not empty
@return [Bool] True if collection is not empty; otherwise false

@overload any()

Checks if there is any item in collection that satisfies given function
@return [Bool] True if collection contains item that satisfies given function; otherwise false
@yield [item] Function used for checking
@yieldparam item [Object] Item of collection
@yieldreturn [Bool] True if item satisfies given function; otherwise false
# File lib/kxi/collections/enumerable.rb, line 139
def any
        if block_given?
                foreach do |item|
                        return true if yield(item)
                end
                return false
        else
                enumerator do |e|
                        return false unless e.rewind
                        return true
                end
        end
end
can_alter?() click to toggle source

Indicates whether collection can be altered @return [Bool] True if collection can be altered; otherwise false

# File lib/kxi/collections/enumerable.rb, line 502
def can_alter?
        @locks == 0 and not @alter
end
count() { |item| ... } click to toggle source

Counts items in collection @return [Number] Number of items @overload count()

Counts the total number of items in collection
@return [Number] Number of items in collection

@overload count()

Counts the number of items that satisfy given function
@return [Number] Number of items that satisfy given function
@yield [item] Function that evaluates whether item should be counted
@yieldparam item [Object] Item of collection
@yieldreturn [Bool] True if item should be counted; otherwise false
# File lib/kxi/collections/enumerable.rb, line 110
def count
        count = 0
        if block_given?
                foreach do |item|
                        count = count + 1 if yield(item)
                end
        else
                enumerator do |e|
                        return 0 unless e.rewind
                        count += 1
                        while e.next
                                count = count + 1
                        end
                end
        end
        return count
end
enumerator() { |create_enumerator| ... } click to toggle source

Allows protected usage of {KXI::Collections::Enumerator} within bounds of block @return [nil] @yield [enumerator] Protected block of code @yieldparam enumerator [KXI::Collections::Enumerator] Enumerator bound to this instance @yieldreturn [void] @raise [KXI::Exceptions::AbstractException] When method {#create_enumerator} is not implemented in superclass

# File lib/kxi/collections/enumerable.rb, line 21
def enumerator
        lock do
                yield(create_enumerator)
        end
        return nil
end
first(df = nil) { |item| ... } click to toggle source

Gets first item, or default @overload first(df = nil)

Gets first item of collection
@param df [Object, nil] Default value
@return [Object, nil] First item of collection; default value if collection is empty

@overload first(df = nil)

Gets first item of collection that satisfies given function
@param df [Object, nil] Default value
@return [Object, nil] First item of collection that satisfies given function; default value if no such item exists
@yield [item] Function for evaluation
@yieldparam item [Object] Item of collection
@yieldreturn [Bool] True if item satisfies given function; false otherwise
# File lib/kxi/collections/enumerable.rb, line 177
def first(df = nil)
        if block_given?
                foreach do |item|
                        return item if yield(item)
                end
        else
                enumerator do |e|
                        return e.current if e.rewind
                end
        end
        return df
end
first!() { |item| ... } click to toggle source

Gets first item @overload first!()

Gets first item of collection
@return [Object, nil] First item of collection
@raise [KXI::Exceptions::CollectionException] Raised when collection is empty

@overload first!()

Gets first item of collection that satisfies given function
@return [Object, nil] First item of collection that satisfies given function
@raise [KXI::Exceptions::CollectionException] Raised when collection contains no element that satisfies given function
@yield [item] Function for evaluation
@yieldparam item [Object] Item of collection
@yieldreturn [Bool] True if item satisfies given function; false otherwise
# File lib/kxi/collections/enumerable.rb, line 203
def first!
        if block_given?
                foreach do |item|
                        return item if yield(item)
                end
        else
                enumerator do |e|
                        return e.current if e.rewind
                end
        end
        raise(KXI::Exceptions::CollectionException.new("Collection contains no #{(block_given? ? 'such ' : '')}items!"))
end
foreach() { |current| ... } click to toggle source

Calls block with each item of collection @return [nil] @yield [item] Function that works with items of collection @yieldparam item [Object] Item of collection @yieldreturn [Void]

# File lib/kxi/collections/enumerable.rb, line 41
def foreach
        enumerator do |e|
                return nil unless e.rewind
                loop do
                        yield(e.current)
                        break unless e.next
                end
        end
        return nil
end
last(df = nil) { |item| ... } click to toggle source

Gets last item, or default @overload last(df = nil)

Gets last item of collection
@param df [Object, nil] Default value
@return [Object, nil] Last item of collection; default value if collection is empty

@overload last(df = nil)

Gets last item of collection that satisfies given function
@param df [Object, nil] Default value
@return [Object, nil] Last item of collection that satisfies given function; default value if no such item exists
@yield [item] Function for evaluation
@yieldparam item [Object] Item of collection
@yieldreturn [Bool] True if item satisfies given function; false otherwise
# File lib/kxi/collections/enumerable.rb, line 228
def last(df = nil)
        found = false
        ret   = nil
        if block_given?
                foreach do |item|
                        if yield(item)
                                ret   = item
                                found = true
                        end
                end
        else
                foreach do |item|
                        ret   = item
                        found = true
                end
        end
        return df unless found
        return ret
end
last!() { |item| ... } click to toggle source

Gets last item @overload last!()

Gets last item of collection
@return [Object, nil] Last item of collection
@raise [KXI::Exceptions::CollectionException] Raised if collection is empty

@overload last!()

Gets last item of collection that satisfies given function
@return [Object, nil] Last item of collection that satisfies given function
@raise [KXI::Exceptions::CollectionException] Raised when collection doesn't contain element that satisfies given function
@yield [item] Function for evaluation
@yieldparam item [Object] Item of collection
@yieldreturn [Bool] True if item satisfies given function; false otherwise
# File lib/kxi/collections/enumerable.rb, line 260
def last!
        found = false
        ret   = nil
        if block_given?
                foreach do |item|
                        if yield(item)
                                ret   = item
                                found = true
                        end
                end
        else
                foreach do |item|
                        ret   = item
                        found = true
                end
        end
        raise(KXI::Exceptions::CollectionException.new("Collection contains no #{(block_given? ? 'such ' : '')}items!")) unless found
        return ret
end
max(&block) click to toggle source

Obtains item with the first maximal value @overload max()

Compares items using spaceship operator (<=>)
@return [Object] Item with first maximal value; nil if collection is empty

@overload max()

Compares items using given comparison function
@return [Object] Item with first maximal value; nil if collection is empty
@yield [what, with] Comparison function
@yieldparam what [Object] Object that is being compared
@yieldparam with [Object] Object that is being compared to
@yieldreturn [Number] Less then 0 if what < with, equal to 0 if what = with and bigger than 0 if what > with
# File lib/kxi/collections/enumerable.rb, line 430
def max(&block)
        block = lambda { |a, b| a <=> b } if block == nil
        ret   = nil
        first = true
        foreach do |i|
                if first
                        ret = i
                        first = false
                elsif block.call(i, ret) > 0
                        ret = i
                end
        end
        return ret
end
min(&block) click to toggle source

Obtains item with the first minimal value @overload min()

Compares items using spaceship operator (<=>)
@return [Object] Item with first minimal value; nil if collection is empty

@overload min()

Compares items using given comparison function
@return [Object] Item with first minimal value; nil if collection is empty
@yield [what, with] Comparison function
@yieldparam what [Object] Object that is being compared
@yieldparam with [Object] Object that is being compared to
@yieldreturn [Number] Less then 0 if what < with, equal to 0 if what = with and bigger than 0 if what > with
# File lib/kxi/collections/enumerable.rb, line 456
def min(&block)
        block = lambda { |a, b| a <=> b } if block == nil
        ret   = nil
        first = true
        foreach do |i|
                if first
                        ret = i
                        first = false
                elsif block.call(i, ret) < 0
                        ret = i
                end
        end
        return ret
end
of_type(*klass) click to toggle source

Selects only those items that are of at least one of specified types @param klass [Class] Types to use for selection @return [KXI::Collections::ArrayCollection] Selected items @see Object#is_a?

# File lib/kxi/collections/enumerable.rb, line 389
def of_type(*klass)
        ret = []
        foreach do |i|
                klass.each do |k|
                        if i.is_a?(k)
                                ret.push(i)
                                break
                        end
                end
        end
        return KXI::Collections::ArrayCollection.new(ret)
end
of_type!(*klass) click to toggle source

Selects only those items that are exactly of at least one of specified types @param klass [Class] Types to use for selection @return [KXI::Collections::ArrayCollection] Selected items @see Object#class

# File lib/kxi/collections/enumerable.rb, line 406
def of_type!(*klass)
        ret = []
        foreach do |i|
                klass.each do |k|
                        if i.class == k
                                ret.push(i)
                                break
                        end
                end
        end
        return KXI::Collections::ArrayCollection.new(ret)
end
order_by(&block) click to toggle source

Orders collection to ascending order @note Ordering is done using merge sort algorithm @return [KXI::Collections::ArrayCollection] Ordered collection @overload order_by()

Orders collection using spaceship operator (<=>)
@return [KXI::Collections::ArrayCollection] Ordered collection

@overload order_by()

Orders collection using given comparison function
@return [KXI::Collections::ArrayCollection] Ordered collection
@yield [what, with] Comparison function
@yieldparam what [Object] Object that is being compared
@yieldparam with [Object] Object that is being compared to
@yieldreturn [Number] Less then 0 if what < with, equal to 0 if what = with and bigger than 0 if what > with
# File lib/kxi/collections/enumerable.rb, line 335
def order_by(&block)
        block  = lambda { |a, b| a <=> b } if block == nil
        groups = []
        g      = []
        foreach do |item|
                if g.length == 0
                        g.push(item)
                else
                        if block.call(g.last, item) <= 0
                                g.push(item)
                        else
                                groups.push(g)
                                g = [item]
                        end
                end
        end
        groups.push(g) if g.length > 0
        return KXI::Collections::ArrayCollection.new if groups.length == 0
        while groups.length > 1
                merges = []
                while groups.length >= 2
                        merges.push(merge(groups.shift, groups.shift, &block))
                end
                merges.push(groups[0]) if groups.length > 0
                groups = merges
        end
        return KXI::Collections::ArrayCollection.new(groups[0])
end
order_by_descending(&block) click to toggle source

Orders collection to descending order @note Ordering is done using merge sort algorithm @return [KXI::Collections::ArrayCollection] Ordered collection @overload order_by()

Orders collection using spaceship operator (<=>)
@return [KXI::Collections::ArrayCollection] Ordered collection

@overload order_by()

Orders collection using given comparison function
@return [KXI::Collections::ArrayCollection] Ordered collection
@yield [what, with] Comparison function
@yieldparam what [Object] Object that is being compared
@yieldparam with [Object] Object that is being compared to
@yieldreturn [Number] Less then 0 if what < with, equal to 0 if what = with and bigger than 0 if what > with
# File lib/kxi/collections/enumerable.rb, line 377
def order_by_descending(&block)
        if block == nil
                return order_by { |a, b| b <=> a }
        else
                return order_by { |a, b| -block.call(a, b) }
        end
end
select() { |i| ... } click to toggle source

Selects specific values @return [KXI::Collections::ArrayCollection] Collection of selected values @yield [item] Function that selects values from items of collection @yieldparam item [Object] Item of collection @yieldreturn [Object] Selected value from item

# File lib/kxi/collections/enumerable.rb, line 57
def select
        ret = []
        foreach do |i|
                ret.push(yield(i))
        end
        return KXI::Collections::ArrayCollection.new(ret)
end
select_many() { |i| ... } click to toggle source

Concatenates selected collections of items @return [KXI::Collections::ArrayCollection] Collection of selected values @yield [item] Function that selects collections of items from given items @yieldparam item [Object] Item of collection @yieldreturn [Array, KXI::Collections::Enumerable] Selected collection of items @raise [KXI::Exceptions::CollectionException] Raised if selection function returns object that is not of type {KXI::Collections::Enumerable} nor Array

# File lib/kxi/collections/enumerable.rb, line 71
def select_many
        ret = []
        foreach do |i|
                col = yield(i)
                if col.is_a?(Array)
                        col.each { |j| ret.push(j) }
                elsif col.is_a?(Enumerable)
                        col.foreach { |j| ret.push(j) }
                else
                        raise(KXI::Exceptions::CollectionException.new('Selection function returned invalid type of object!'))
                end
        end
        return KXI::Collections::ArrayCollection.new(ret)
end
skip(count) click to toggle source

Skips given number of items and returns the rest @param count [Number] Number of items to skip @return [KXI::Collections::ArrayCollection] Collection of items that weren't skipped

# File lib/kxi/collections/enumerable.rb, line 283
def skip(count)
        ret = []
        foreach do |item|
                if count > 0
                        count -= 1
                else
                        ret.push(item)
                end
        end
        return KXI::Collections::ArrayCollection.new(ret)
end
take(count) click to toggle source

Returns first N elements @param count [Number] Number of items to take @return [KXI::Collections::ArrayCollection] Collection of first N items

# File lib/kxi/collections/enumerable.rb, line 298
def take(count)
        ret = []
        foreach do |item|
                break unless count > 0
                count -= 1
                ret.push(item)
        end
        return KXI::Collections::ArrayCollection.new(ret)
end
to_array() click to toggle source

Coverts collection to array @return [Array] Array equivalent to collection

# File lib/kxi/collections/enumerable.rb, line 473
def to_array
        ret = []
        foreach { |item| ret.push(item) }
        return ret
end
where() { |i| ... } click to toggle source

Selects only those items that satisfy given function @return [KXI::Collections::ArrayCollection] Collection of selected items @yield [item] Function that evaluates whether item should be selected @yieldparam item [Object] Item of collection @yieldreturn [Bool] True if item should be selected; otherwise false

# File lib/kxi/collections/enumerable.rb, line 91
def where
        ret = []
        foreach do |i|
                ret.push(i) if yield(i)
        end
        return KXI::Collections::ArrayCollection.new(ret)
end

Protected Instance Methods

create_enumerator() click to toggle source

Creates a new {KXI::Collections::Enumerator} bound to this instance @return [KXI::Collections::Enumerator] Enumerator bound to this instance @raise [KXI::Exceptions::AbstractException] When method is not implemented in superclass @abstract

# File lib/kxi/collections/enumerable.rb, line 32
def create_enumerator
        raise(KXI::Exceptions::AbstractException.new(Enumerable))
end
lock(write = false) { || ... } click to toggle source
# File lib/kxi/collections/enumerable.rb, line 506
def lock(write = false)
        if write
                raise(KXI::Exceptions::CollectionException.new('Collection cannot be locked for writing!')) unless can_alter?
                @alter = true
                yield
        else
                raise(KXI::Exceptions::CollectionException.new('Collection cannot be locked for reading!')) if @alter
                @locks += 1
                yield
        end
ensure
        if write
                @alter = false
        else
                @locks -= 1
        end
end

Private Instance Methods

merge(a, b, &comp) click to toggle source

Merges two arrays in order using comparison function @param a [Array] First array @param b [Array] Second array @return [Array] Merged ordered array

# File lib/kxi/collections/enumerable.rb, line 483
def merge(a, b, &comp)
        ret = []
        while a.length > 0 or b.length > 0
                if a.length > 0 and b.length > 0
                        c = comp.call(a[0], b[0])
                        if c <= 0
                                ret.push(a.shift)
                        else
                                ret.push(b.shift)
                        end
                else
                        ret.push(a.length > 0 ? a.shift : b.shift)
                end
        end
        return ret
end