Module: Indexable
Overview
Indexable is a mixin that provides index based methods, working solely 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 method 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 following 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
Instance Method Summary collapse
-
#body ⇒ Object
Returns an array of the first element up to, but not including, the last element.
-
#ends ⇒ Object
A shorting of “ends at”, returns the last index of the indexable object.
-
#first(n = 1) ⇒ Object
Returns first n elements.
-
#first! ⇒ Object
Remove and return the first element.
-
#first=(x) ⇒ Object
Change the first element.
-
#foot ⇒ Object
Like #last, returning the last element in an array.
-
#from(i) ⇒ Object
Returns last n elements.
-
#head ⇒ Object
Like #first but returns the first element in a new array.
-
#index(obj = nil, &block) ⇒ Object
(also: #index_of)
Returns the index of the first element equal to the given object or satisfying the block condition.
-
#last(n = 1) ⇒ Object
Returns last n elements.
-
#last! ⇒ Object
Remove and return the last element.
-
#last=(x) ⇒ Object
Change the last element.
-
#mid(offset = 0) ⇒ Object
Returns the middle element of an array, or the element offset from middle if the parameter is given.
-
#middle(birth = 0) ⇒ Object
Returns an Array of the middle element(s) of an array.
-
#pos(i) ⇒ Object
Returns the positive ordinal index given a cardinal position, 1 to n or -n to -1.
-
#range(a = nil, z = -1)) ⇒ Object
Returns the index range between two elements.
-
#tail ⇒ Object
Returns an array from second element to last element.
-
#thru(from, to = nil) ⇒ Object
Fetch values from a start index through an end index.
Instance Method Details
#body ⇒ Object
Returns an array of the first element up to, but not including, the last element.
[1,2,3].body #=> [1,2]
– Better name for this? (bulk, perhaps?) ++
61 62 63 |
# File 'lib/core/facets/indexable.rb', line 61 def body slice(0,size-1) end |
#ends ⇒ Object
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.
210 211 212 213 |
# File 'lib/core/facets/indexable.rb', line 210 def ends return nil if size == 0 size - 1 end |
#first(n = 1) ⇒ Object
Returns first n elements.
%w{H e l l o}.first(3) #=> %w{H e l}
148 149 150 |
# File 'lib/core/facets/indexable.rb', line 148 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]
188 189 190 |
# File 'lib/core/facets/indexable.rb', line 188 def first! splice(0) end |
#first=(x) ⇒ Object
Change the first element.
a = ["a","y","z"]
a.first = "x"
a #=> ["x","y","z"]
168 169 170 |
# File 'lib/core/facets/indexable.rb', line 168 def first=(x) splice(0,x) end |
#foot ⇒ Object
Like #last, returning the last element in an array.
[1,2,3].foot #=> [3]
48 49 50 |
# File 'lib/core/facets/indexable.rb', line 48 def foot slice(-1,1) end |
#from(i) ⇒ Object
Returns last n elements.
%w{W o r l d}.from(3) #=> %w{l d}
130 131 132 133 |
# File 'lib/core/facets/indexable.rb', line 130 def from(i) return [] if i >= size slice(i, size - i) #slice(-n..-1) end |
#head ⇒ Object
Like #first but returns the first element in a new array.
[1,2,3].head #=> [1]
31 32 33 |
# File 'lib/core/facets/indexable.rb', line 31 def head slice(0,1) end |
#index(obj = nil, &block) ⇒ Object Also known as: index_of
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
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/core/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 |
#last(n = 1) ⇒ Object
Returns last n elements.
%w{H e l l o}.last(3) #=> %w{l l o}
156 157 158 159 160 |
# File 'lib/core/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! ⇒ Object
Remove and return the last element.
a = [1,2,3]
a.last! #=> 3
a #=> [1,2]
198 199 200 |
# File 'lib/core/facets/indexable.rb', line 198 def last! splice(-1) end |
#last=(x) ⇒ Object
Change the last element.
a = [1,2,5]
a.last = 3
a #=> [1,2,3]
178 179 180 |
# File 'lib/core/facets/indexable.rb', line 178 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 origin (0).
79 80 81 |
# File 'lib/core/facets/indexable.rb', line 79 def mid(offset=0) slice((size / 2) + offset) end |
#middle(birth = 0) ⇒ Object
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.
97 98 99 100 101 102 103 104 |
# File 'lib/core/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) ⇒ 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
221 222 223 224 225 226 227 |
# File 'lib/core/facets/indexable.rb', line 221 def pos(i) if i > 0 return i - 1 else size + i end end |
#range(a = nil, z = -1)) ⇒ 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..3)
259 260 261 262 263 264 265 |
# File 'lib/core/facets/indexable.rb', line 259 def range(a=nil,z=-1) if a index(a)..index(z) else (0..(size-1)) end end |
#tail ⇒ Object
Returns an array from second element to last element.
[1,2,3].tail #=> [2,3]
39 40 41 |
# File 'lib/core/facets/indexable.rb', line 39 def tail slice(1,length-1) end |
#thru(from, to = nil) ⇒ Object
Fetch values from a start index through 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]
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/core/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 |