# module Indexable

Indexable is a mixin that provides index based methods, working soley with four methods: index, slice, splice and size.

These methods work in harmony. Where index returns a position of a given element, slice returns elements for given positions. splice is like slice but replaces the given position with new values. This mehtod is not part of ruby core, but it generally just an alias for []=, just as slice is an alias of []. size of course simply returns the total length of the indexable object.

NOTE: To test the folowing methods Indexable needs to be included into Array and array must have splice defined.

    require 'facets/array/splice'

    class ::Array
      include Indexable
    end

CREDIT: Thomas Sawyer

### Public Instance Methods

body() click to toggle source

Returns an array of the first element upto, but not including, the last element.

    [1,2,3].body  #=> [1,2]

    # File lib/facets/indexable.rb, line 61
    def body
      slice(0,size-1)
    end

ends() click to toggle source

A shorting of “ends at”, returns the last index of the indexable object. Returns nil if there are no elements.

    [1,2,3,4,5].ends  #=> 4

This nearly equivalent to +size - 1+.

    # File lib/facets/indexable.rb, line 210
    def ends
      return nil if size == 0
      size - 1
    end

first(n=1) click to toggle source

Returns first n elements.

    %w{H e l l o}.first(3)  #=> %w{H e l}

    # File lib/facets/indexable.rb, line 148
    def first(n=1)
      slice(0, n.to_i)
    end

first!() click to toggle source

Remove and return the first element.

    a = [1,2,3]
    a.first!      #=> 1
    a             #=> [2,3]

    # File lib/facets/indexable.rb, line 188
    def first!
      splice(0)
    end

first=(x) click to toggle source

Change the first element.

    a = ["a","y","z"]
    a.first = "x"
    a           #=> ["x","y","z"]

    # File lib/facets/indexable.rb, line 168
    def first=(x)
      splice(0,x)
    end

foot() click to toggle source

Like last, returning the last element in an array.

    [1,2,3].foot  #=> [3]

    # File lib/facets/indexable.rb, line 48
    def foot
      slice(-1,1)
    end

from(i) click to toggle source

Returns last n elements.

    %w{W o r l d}.from(3)  #=> %w{l d}

    # File lib/facets/indexable.rb, line 130
    def from(i)
      return self if i >= size
      slice(i, size - i) #slice(-n..-1)
    end

head() click to toggle source

Like first but returns the first element in a new array.

    [1,2,3].head  #=> [1]

    # File lib/facets/indexable.rb, line 31
    def head
      slice(0,1)
    end

index(obj=nil) { |slice(i)| ... } click to toggle source

Returns the index of the first element equal to the given object or satisfying the block condition.

    [1,2,3,4].index{ |e| e == 3 }  #=> 2
    [1,2,3,4].index{ |e| e > 3 }   #=> 3

    # File lib/facets/indexable.rb, line 235
    def index(obj=nil, &block)
      if block_given?
        size.times do |i|
          return i if yield(slice(i))
        end
      else
        size.times do |i|
          return i if obj == slice(i)
        end
      end
      nil
    end

Also aliased as: index_of
index_of(obj=nil, &block)

to be deprecated

Alias for: index
last(n=1) click to toggle source

Returns last n elements.

    %w{H e l l o}.last(3)  #=> %w{l l o}

    # File lib/facets/indexable.rb, line 156
    def last(n=1)
      n = n.to_i
      return self if n > size
      slice(-n, n) #slice(-n..-1)
    end

last!() click to toggle source

Remove and return the last element.

    a = [1,2,3]
    a.last!       #=> 3
    a             #=> [1,2]

    # File lib/facets/indexable.rb, line 198
    def last!
      splice(-1)
    end

last=(x) click to toggle source

Change the last element.

    a = [1,2,5]
    a.last = 3
    a           #=> [1,2,3]

    # File lib/facets/indexable.rb, line 178
    def last=(x)
      splice(-1,x)
    end

mid(offset=0) click to toggle source

Returns the middle element of an array, or the element offset from middle if the parameter is given. Even-sized arrays, not having an exact middle, return the middle-right element.

    [1,2,3,4,5].mid        #=> 3
    [1,2,3,4,5,6].mid      #=> 4
    [1,2,3,4,5,6].mid(-1)  #=> 3
    [1,2,3,4,5,6].mid(-2)  #=> 2
    [1,2,3,4,5,6].mid(1)   #=> 5

In other words, If there are an even number of elements the higher-indexed of the two center elements is indexed as orgin (0).

    # File lib/facets/indexable.rb, line 79
    def mid(offset=0)
      slice((size / 2) + offset)
    end

middle(birth=0) click to toggle source

Returns an Array of the middle element(s) of an array. Even-sized arrays, not having an exact middle, return a two-element array of the two middle elements.

    [1,2,3,4,5].middle        #=> [3]
    [1,2,3,4,5,6].middle      #=> [3,4]

A `birth` can be give to widen the middle on either side.

    [1,2,3,4,5].middle(1)   #=> [2,3,4]
    [1,2,3,4,5,6].middle(1)   #=> [2,3,4,5]

In contrast to mid which utilizes an offset.

    # File lib/facets/indexable.rb, line 97
    def middle(birth=0)
      i = size / 2 - birth
      if size % 2 == 0
        slice(i - 1, 2 + (2 * birth))
      else
        slice(i, 1 + (2 * birth))
      end
    end

pos(i) click to toggle source

Returns the positive ordinal index given a cardinal position, 1 to n or -n to -1.

    [1,2,3,4,5].pos(1)   #=> 0
    [1,2,3,4,5].pos(-1)  #=> 4

    # File lib/facets/indexable.rb, line 221
    def pos(i)
      if i > 0
        return i - 1
      else
        size + i
      end
    end

range(a=nil,z=-1) click to toggle source

Returns the index range between two elements. If no elements are given, returns the range from first to last.

    ['a','b','c','d'].range            #=> (0..3)
    ['a','b','c','d'].range('b','d')   #=> (1..3)

    # File lib/facets/indexable.rb, line 259
    def range(a=nil,z=-1)
      if a
        index(a)..index(z)
      else
        (0..(size-1))
      end
    end

tail() click to toggle source

Returns an array from second element to last element.

    [1,2,3].tail  #=> [2,3]

    # File lib/facets/indexable.rb, line 39
    def tail
      slice(1,length-1)
    end

thru(from, to=nil) click to toggle source

Fetch values from a start index thru an end index.

    [1,2,3,4,5].thru(0,2)  #=> [1,2,3]
    [1,2,3,4,5].thru(2,4)  #=> [3,4,5]

    [1,2,3,4,5].thru(2)  #=> [1,2,3]
    [1,2,3,4,5].thru(4)  #=> [1,2,3,4,5]

    # File lib/facets/indexable.rb, line 114
    def thru(from, to=nil)
      from, to = 0, from unless to
      to = size - 1 if to >= size
      a = []
      i = from
      while i <= to
        a << slice(i)
        i += 1
      end
      a
    end