ntable 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ === 0.1.6 / 2012-09-24
2
+
3
+ * It is now possible to specify a fixed structure for NTable.from_nested_object.
4
+
1
5
  === 0.1.5 / 2012-09-24
2
6
 
3
7
  * INCOMPATIBLE CHANGE: Renamed :postprocess option in NTable.from_nested_object to :postprocess_labels.
data/Version CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.1.6
@@ -153,13 +153,24 @@ module NTable
153
153
  # [<tt>:stringify_by_default</tt>]
154
154
  # If set to a Proc, this Proc is used as the default stringification
155
155
  # routine for converting labels for a LabeledAxis.
156
+ # [<tt>:structure</tt>]
157
+ # Force the use of the given Structure. Any data that does not fit
158
+ # into this structure is ignored. When this option is provided,
159
+ # the :name, :sort, :postprocess_labels, and :postprocess_range
160
+ # field options are ignored. However, :stringify and :objectify may
161
+ # still be provided to specify how hash keys should map to labels.
156
162
 
157
163
  def from_nested_object(obj_, field_opts_=[], opts_={})
164
+ if field_opts_.is_a?(::Hash)
165
+ opts_ = field_opts_
166
+ field_opts_ = []
167
+ end
158
168
  axis_data_ = []
159
169
  _populate_nested_axes(axis_data_, 0, obj_)
160
170
  objectify_by_default_ = opts_[:objectify_by_default]
161
171
  stringify_by_default_ = opts_[:stringify_by_default]
162
- struct_ = Structure.new
172
+ fixed_struct_ = opts_[:structure]
173
+ struct_ = Structure.new unless fixed_struct_
163
174
  axis_data_.each_with_index do |ai_, i_|
164
175
  field_ = field_opts_[i_] || {}
165
176
  axis_ = nil
@@ -184,7 +195,7 @@ module NTable
184
195
  klass_ = ObjectAxis
185
196
  else
186
197
  stringify_ = nil unless stringify_.respond_to?(:call)
187
- h_ = ::Set.new
198
+ h_ = ::Set.new
188
199
  ai_.keys.each do |k_|
189
200
  nv_ = (stringify_ ? stringify_.call(k_) : k_).to_s
190
201
  ai_[k_] = nv_
@@ -193,35 +204,39 @@ module NTable
193
204
  labels_ = h_.to_a
194
205
  klass_ = LabeledAxis
195
206
  end
196
- if (sort_ = field_[:sort])
197
- if sort_.respond_to?(:call)
198
- func_ = sort_
199
- elsif sort_ == :string
200
- func_ = @string_sort
201
- elsif sort_ == :integer
202
- func_ = @integer_sort
203
- elsif sort_ == :numeric
204
- func_ = @numeric_sort
205
- else
206
- func_ = nil
207
+ if struct_
208
+ if (sort_ = field_[:sort])
209
+ if sort_.respond_to?(:call)
210
+ func_ = sort_
211
+ elsif sort_ == :string
212
+ func_ = @string_sort
213
+ elsif sort_ == :integer
214
+ func_ = @integer_sort
215
+ elsif sort_ == :numeric
216
+ func_ = @numeric_sort
217
+ else
218
+ func_ = nil
219
+ end
220
+ labels_.sort!(&func_)
207
221
  end
208
- labels_.sort!(&func_)
222
+ postprocess_ = field_[:postprocess_labels]
223
+ labels_ = postprocess_.call(labels_) || labels_ if postprocess_.respond_to?(:call)
224
+ axis_ = klass_.new(labels_)
209
225
  end
210
- postprocess_ = field_[:postprocess_labels]
211
- labels_ = postprocess_.call(labels_) || labels_ if postprocess_.respond_to?(:call)
212
- axis_ = klass_.new(labels_)
213
226
  when ::Array
214
- range_ = ((ai_[0].to_i)...(ai_[1].to_i))
215
- postprocess_ = field_[:postprocess_range]
216
- range_ = postprocess_.call(range_) || range_ if postprocess_.respond_to?(:call)
217
- ai_[0] = range_.first.to_i
218
- ai_[1] = range_.last.to_i
219
- ai_[1] += 1 unless range_.exclude_end?
220
- axis_ = IndexedAxis.new(ai_[1] - ai_[0], ai_[0])
227
+ if struct_
228
+ range_ = ((ai_[0].to_i)...(ai_[1].to_i))
229
+ postprocess_ = field_[:postprocess_range]
230
+ range_ = postprocess_.call(range_) || range_ if postprocess_.respond_to?(:call)
231
+ ai_[0] = range_.first.to_i
232
+ ai_[1] = range_.last.to_i
233
+ ai_[1] += 1 unless range_.exclude_end?
234
+ axis_ = IndexedAxis.new(ai_[1] - ai_[0], ai_[0])
235
+ end
221
236
  end
222
237
  struct_.add(axis_, name_) if axis_
223
238
  end
224
- table_ = Table.new(struct_, :fill => opts_[:fill])
239
+ table_ = Table.new(fixed_struct_ || struct_, :fill => opts_[:fill])
225
240
  _populate_nested_values(table_, [], axis_data_, obj_)
226
241
  table_
227
242
  end
@@ -233,6 +233,36 @@ module NTable
233
233
  end
234
234
 
235
235
 
236
+ def test_integer_sort
237
+ obj_ = {'9' => 1, '10' => 2}
238
+ t1_ = Table.from_nested_object(obj_, [{:sort => :integer}])
239
+ assert_equal(['9', '10'], t1_.structure.axis(0).to_a)
240
+ end
241
+
242
+
243
+ def test_custom_sort
244
+ sorter_ = ->(a_, b_){ b_.to_i <=> a_.to_i }
245
+ obj_ = {'9' => 1, '10' => 2, '11' => 3}
246
+ t1_ = Table.from_nested_object(obj_, [{:sort => sorter_}])
247
+ assert_equal(['11', '10', '9'], t1_.structure.axis(0).to_a)
248
+ end
249
+
250
+
251
+ def test_custom_object_sort
252
+ sorter_ = ->(a_, b_){ b_.to_s.to_i <=> a_.to_s.to_i }
253
+ obj_ = {:'9' => 1, :'10' => 2, :'11' => 3}
254
+ t1_ = Table.from_nested_object(obj_, [{:sort => sorter_, :objectify => true}])
255
+ assert_equal([:'11', :'10', :'9'], t1_.structure.axis(0).to_a)
256
+ end
257
+
258
+
259
+ def test_fixed_struct
260
+ struct_ = Structure.add(@indexed_axis_2, 'row').add(@labeled_axis_3, 'col')
261
+ t1_ = Table.from_nested_object(nil, :structure => struct_, :fill => 0)
262
+ assert_equal(Table.new(struct_, :load => [0, 0, 0, 0, 0, 0]), t1_)
263
+ end
264
+
265
+
236
266
  end
237
267
 
238
268
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ntable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-24 00:00:00.000000000 Z
12
+ date: 2012-09-25 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: NTable provides a convenient data structure for storing n-dimensional
15
15
  tabular data. It works with zero-dimensional scalar values, arrays, tables, and