Class: NArray
- Inherits:
-
Array
- Object
- Array
- NArray
- Defined in:
- lib/n-array.rb
Overview
Multidimensional array for Ruby
Defined Under Namespace
Classes: EmptyArgument
Instance Attribute Summary collapse
-
#dimensions ⇒ Object
readonly
Returns the value of attribute dimensions.
Class Method Summary collapse
-
.[](*description) ⇒ Object
Create a n-array fitting the given description.
- ._arg?(arg) ⇒ Boolean
- ._extract(args) ⇒ Object
-
.calculate_dimensions(array) ⇒ Object
Returns an array of lengths for an array (only works with Array, don’t ask me why).
-
.count_dimensions(array) ⇒ Object
Returns the number of dimensions that can be generated from the argument while keeping the array well-formed.
-
.is_valid_description?(dimensions) ⇒ Boolean
Check whether the argument is a valid description of dimensions.
-
.is_valid_dimension?(dimensions) ⇒ Boolean
Check whether the argument is a valid dimension.
Instance Method Summary collapse
-
#[](*pos) ⇒ Object
Fetch the value at the position of the arguments.
-
#[]=(*pos, v) ⇒ Object
Sets the value at the position of the arguments.
-
#collect ⇒ Object
See #map.
-
#each(&blck) ⇒ Object
Iterate over the elements of the n-array applying the given block to each element.
-
#initialize(dimensions = nil, *values, &blck) ⇒ NArray
constructor
A new instance of NArray.
-
#length(d = 0) ⇒ Object
Returns the length of the dimension given as parameter.
-
#lengths ⇒ Object
Returns an array of the lengths of each dimension.
-
#map(&blck) ⇒ Object
Iterate over the elements of the n-array apply the given bloc and collect the results into a nested collection of arrays identical to the structure of the caller.
-
#size ⇒ Object
Returns the total number of elements in the n-array.
Constructor Details
#initialize(dimensions = nil, *values, &blck) ⇒ NArray
Returns a new instance of NArray.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/n-array.rb', line 5 def initialize dimensions = nil, *values, &blck # Make a difference between no arguments and nil values = NArray::_extract values # In case the only parameter is a NArray, duplicate it if dimensions.is_a? NArray and !NArray::_arg? values self.replace dimensions.dup # In case the parameter is an array, multiple possibilities elsif dimensions.is_a? Array # 1) The array decribes dimensions and provide a default value to fill in the blanks if NArray.is_valid_description? dimensions and (NArray::_arg? values or block_given?) # then we build the n-array recursively and fill the values with what has been provided @dimensions = dimensions.length @dimensions == 1 ? # A little detour to avoid warnings on nil values !NArray::_arg?(values) ? super(dimensions[0], &blck) : super(dimensions[0], values) : super( [*0...dimensions[0]].map { NArray.new(dimensions.drop(1), values, &blck) } ) # 2) the array does not provide a default value elsif !NArray::_arg? values and !block_given? # then we create a NArray fitting the litteral given @dimensions = NArray.count_dimensions dimensions #inefficient but GTD @dimensions == 1 ? super(dimensions) : # giving a block here has no effect with mri and the doc doesn't say anything super(dimensions.map { |e| NArray.new(e) }) # 3) the array is not a valid description but a default value is given, i.e. user mistake. Scold him! else raise RuntimeError, "#{dimensions} is not a valid description: An array of striclty positive Integers is expected" end # In case the dimension is valid elsif NArray.is_valid_dimension? dimensions @dimensions = dimensions if dimensions == 1 super([], &blck) else super([NArray.new(dimensions - 1, values, &blck)]) end # Empty constructor elsif dimensions.nil? and !NArray::_arg? values super(&blck) # Bad user, bad else raise RuntimeError \ "Invalid dimension (expecting an Integer or array of Integer all strictly positives, got #{dimensions}" end end |
Instance Attribute Details
#dimensions ⇒ Object (readonly)
Returns the value of attribute dimensions.
4 5 6 |
# File 'lib/n-array.rb', line 4 def dimensions @dimensions end |
Class Method Details
.[](*description) ⇒ Object
Create a n-array fitting the given description
154 155 156 |
# File 'lib/n-array.rb', line 154 def[] *description NArray.new(description) end |
._arg?(arg) ⇒ Boolean
197 198 199 |
# File 'lib/n-array.rb', line 197 def _arg? arg !arg.is_a? NArray::EmptyArgument end |
._extract(args) ⇒ Object
192 193 194 195 |
# File 'lib/n-array.rb', line 192 def _extract args raise ParameterError, "Expected 1..2 arguments, got #{args.length + 1}" if args.length > 1 args.length == 1 ? args[0] : NArray::EmptyArgument.new end |
.calculate_dimensions(array) ⇒ Object
Returns an array of lengths for an array (only works with Array, don’t ask me why)
Each dimension in a n-array has a maximum size, those are collected and ordered into an array, the first being the top array, and the last the deepest group
134 135 136 |
# File 'lib/n-array.rb', line 134 def calculate_dimensions array _count(array).take_while { |e| e >= 0 } end |
.count_dimensions(array) ⇒ Object
Returns the number of dimensions that can be generated from the argument while keeping the array well-formed
Checks the maximum level of nesting so that any n-vector v2…vn with 0 <= vm < length(m) correctly refers to an element in the structure
126 127 128 |
# File 'lib/n-array.rb', line 126 def count_dimensions array array.class == NArray ? array.dimensions : calculate_dimensions(array).length end |
.is_valid_description?(dimensions) ⇒ Boolean
Check whether the argument is a valid description of dimensions
Returns true if the argument is an Array of values satisfying is_valid_dimension?, false otherwise
149 150 151 |
# File 'lib/n-array.rb', line 149 def is_valid_description? dimensions dimensions.is_a? Array and dimensions.all? { |e| is_valid_dimension? e } end |
.is_valid_dimension?(dimensions) ⇒ Boolean
Check whether the argument is a valid dimension
Returns true if dimensions is a strictly positive Integer, false otherwise
142 143 144 |
# File 'lib/n-array.rb', line 142 def is_valid_dimension? dimensions dimensions.is_a? Integer and dimensions > 0 end |
Instance Method Details
#[](*pos) ⇒ Object
Fetch the value at the position of the arguments
In case the argument contains nil values, returns a NArray of the elements satisfying the coordinates given by the arguments (to-do)
78 79 80 81 |
# File 'lib/n-array.rb', line 78 def [] *pos raise "1..#{dimensions} arguments expected, given #{pos.length}" if pos.length > dimensions or pos.length == 0 pos.length == 1 ? super(*pos) : super(pos[0])[*pos.drop(1)] end |
#[]=(*pos, v) ⇒ Object
Sets the value at the position of the arguments
84 85 86 87 |
# File 'lib/n-array.rb', line 84 def []= *pos, v raise "#{dimensions} arguments expected, given #{pos.length}" if pos.length != dimensions pos.length == 1 ? super(*pos, v) : self[pos[0]][*pos.drop(1)] = v end |
#collect ⇒ Object
See #map
117 118 119 |
# File 'lib/n-array.rb', line 117 def collect map end |
#each(&blck) ⇒ Object
Iterate over the elements of the n-array applying the given block to each element
95 96 97 98 99 100 101 102 103 |
# File 'lib/n-array.rb', line 95 def each &blck if dimensions > 1 super() do |e| e.each(&blck) end else super(&blck) end end |
#length(d = 0) ⇒ Object
Returns the length of the dimension given as parameter
Starts at 0
67 68 69 70 |
# File 'lib/n-array.rb', line 67 def length d = 0 raise "Expecting positive Integer < #{dimensions}, got #{d}" unless d < dimensions and d >= 0 d == 0 ? super() : self[0].length(d - 1) end |
#lengths ⇒ Object
Returns an array of the lengths of each dimension
59 60 61 62 |
# File 'lib/n-array.rb', line 59 def lengths #NArray.calculate_dimensions(self) # doesn't work for some weird reason dimensions == 1 ? [length] : [length, *self[0].lengths] end |
#map(&blck) ⇒ Object
Iterate over the elements of the n-array apply the given bloc and collect the results into a nested collection of arrays identical to the structure of the caller
107 108 109 110 111 112 113 114 115 |
# File 'lib/n-array.rb', line 107 def map &blck if dimensions > 1 super() do |e| e.map(&blck) end else super(&blck) end end |
#size ⇒ Object
Returns the total number of elements in the n-array
90 91 92 |
# File 'lib/n-array.rb', line 90 def size lengths.reduce(&:*) end |