Module: Indexable

Included in:
Array, String
Defined in:
lib/core/facets/indexable.rb

Overview

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.

Instance Method Summary collapse

Instance Method Details

#bodyObject

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

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

– Better name for this? (bulk, perhaps?) ++



70
71
72
# File 'lib/core/facets/indexable.rb', line 70

def body
  slice(0,size-1)
end

#endsObject

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.



191
192
193
194
# File 'lib/core/facets/indexable.rb', line 191

def ends
  return nil if size == 0
  size - 1
end

#first(n = 1) ⇒ Object

Returns first n elements.

"Hello World".first(3)  #=> "Hel"


129
130
131
# File 'lib/core/facets/indexable.rb', line 129

def first(n=1)
  slice(0, n.to_i)
end

#first!Object

Remove and return the first element.

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


169
170
171
# File 'lib/core/facets/indexable.rb', line 169

def first!
  splice(0)
end

#first=(x) ⇒ Object

Change the first element.

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


149
150
151
# File 'lib/core/facets/indexable.rb', line 149

def first=(x)
  splice(0,x)
end

#footObject

Like #last, returning the last element in an array.

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


57
58
59
# File 'lib/core/facets/indexable.rb', line 57

def foot
  slice(-1,1)
end

#headObject

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

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


40
41
42
# File 'lib/core/facets/indexable.rb', line 40

def head
  slice(0,1)
end

#index_of(obj = nil, &blk) ⇒ Object

Returns the index of the first element to satisfy the block condition. This is simply #index with a block.

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

TODO: Remove Array#index_of when Ruby 1.9 adds block to #index.



218
219
220
221
222
# File 'lib/core/facets/indexable.rb', line 218

def index_of(obj=nil,&blk)
  return index(obj) unless block_given?
  i=0; i+=1 until yield(self[i])
  return i
end

#last(n = 1) ⇒ Object

Returns last n elements.

"Hello World".last(3)  #=> "rld"


137
138
139
140
141
# File 'lib/core/facets/indexable.rb', line 137

def last(n=1)
  n = n.to_i
  return self if n > size
  slice(-n, n) #slice(-n..-1)
end

#last!Object

Remove and return the last element.

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


179
180
181
# File 'lib/core/facets/indexable.rb', line 179

def last!
  splice(-1)
end

#last=(x) ⇒ Object

Change the last element.

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


159
160
161
# File 'lib/core/facets/indexable.rb', line 159

def last=(x)
  splice(-1,x)
end

#mid(offset = 0) ⇒ Object

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).



88
89
90
# File 'lib/core/facets/indexable.rb', line 88

def mid(offset=0)
  slice((size / 2) + offset)
end

#middleObject

Returns the middle element(s) of an array. Even-sized arrays, not having an exact middle, returns 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]

In contrast to #mid which utilizes an offset.



101
102
103
104
105
106
107
108
# File 'lib/core/facets/indexable.rb', line 101

def middle
  if size % 2 == 0
   slice( (size / 2) - 1, 2 )
   #[slice((size / 2) - 1, 1), slice(size / 2, 1)]
  else
    slice(size / 2)
  end
end

#pos(i) ⇒ Object

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


202
203
204
205
206
207
208
# File 'lib/core/facets/indexable.rb', line 202

def pos(i)
  if i > 0
    return i - 1
  else
    size + i
  end
end

#range(a = nil, z = nil) ⇒ Object

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..2


233
234
235
236
237
238
239
# File 'lib/core/facets/indexable.rb', line 233

def range(a=nil,z=nil)
  if !a
    0..(size-1)
  else
    index(a)..index(z)
  end
end

#tailObject

Returns an array from second element to last element.

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


48
49
50
# File 'lib/core/facets/indexable.rb', line 48

def tail
  slice(1,length-1)
end

#thru(from, to) ⇒ Object

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]


115
116
117
118
119
120
121
122
123
# File 'lib/core/facets/indexable.rb', line 115

def thru(from, to)
  a = []
  i = from
  while i <= to
    a << slice(i)
    i += 1
  end
  a
end