fat_table 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.org +9 -5
- data/lib/ext/array.rb +17 -0
- data/lib/fat_table/column.rb +19 -20
- data/lib/fat_table/convert.rb +14 -1
- data/lib/fat_table/evaluator.rb +6 -8
- data/lib/fat_table/formatters/formatter.rb +8 -7
- data/lib/fat_table/table.rb +10 -3
- data/lib/fat_table/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ecb8cb3fb29acb95b0fe11e65c5b587379a5a3070ab68acbc6a2c1785c8f229
|
4
|
+
data.tar.gz: f3cc9e7242ded9fd0970159eee8da4208faade0e6e4c37a324a45e1596c4eeae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d404bd69ba3a1c3c9774f634e4f0935987ff4827803d59e89b9adbdc4806b25ef87e5dbcb9f22d7e3475c86dceebf097cf73e0ad1287f91d21415e5b0a5a3b3
|
7
|
+
data.tar.gz: 8d8df3651b9cdcdeaefa0527cd4fc1987c1ec491bca2a88651b255032eea16ee29c82285b9d7f9bae2ecb9b6d90c6fc4d766980af5362dc89045d553e66dec03
|
data/README.org
CHANGED
@@ -638,8 +638,11 @@ something that can't be parsed as a Numeric. ~FatTable~ raises an exception
|
|
638
638
|
is such cases, and that may be what you want if you can control the input.
|
639
639
|
But, especially when you cannot do so, it can be helpful to designate one or
|
640
640
|
more columns as "tolerant." This means that when a conversion problem occurs,
|
641
|
-
the column is
|
642
|
-
|
641
|
+
the column item is retained as a string type in a column that is otherwise of
|
642
|
+
one of the types Numeric, DateTime, or Boolean. Those string items are
|
643
|
+
treated as nils for purposes of sorting or evaluation in a ~select~ method.
|
644
|
+
When formatted, they participate in string formatting directive, but not those
|
645
|
+
for other types.
|
643
646
|
|
644
647
|
All of the table construction methods, allow a keyword parameter,
|
645
648
|
~tolerant_columns~, where you can designate what columns should be convert to
|
@@ -2641,9 +2644,10 @@ the table, but they can be overridden by more specific directives given in a
|
|
2641
2644
|
~format_for~ directive.
|
2642
2645
|
|
2643
2646
|
**** Type and Column priority
|
2644
|
-
A directive based
|
2645
|
-
|
2646
|
-
|
2647
|
+
A directive based the column name overrides any directive based on type. If
|
2648
|
+
any cell has both a type-based formatting and column-based, the column
|
2649
|
+
instructions prevail. In earlier versions the instuctions were "merged" but
|
2650
|
+
that is no longer the case.
|
2647
2651
|
|
2648
2652
|
However, there is a twist. Since the end result of formatting is to convert
|
2649
2653
|
all columns to strings, the formatting directives for the ~String~ type can
|
data/lib/ext/array.rb
CHANGED
@@ -12,4 +12,21 @@ class Array
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
def filter_to_type(typ)
|
17
|
+
if typ == 'Boolean'
|
18
|
+
compact.select { |i| i.is_a?(TrueClass) || i.is_a?(FalseClass) }
|
19
|
+
elsif typ == 'DateTime'
|
20
|
+
compact.select { |i| i.is_a?(Date) || i.is_a?(DateTime) || i.is_a?(Time) }
|
21
|
+
.map { |i| i.to_datetime }
|
22
|
+
elsif typ == 'Numeric'
|
23
|
+
compact.select { |i| i.is_a?(Numeric) }
|
24
|
+
elsif typ == 'String'
|
25
|
+
map { |i| i.to_s }
|
26
|
+
elsif typ == 'NilClass'
|
27
|
+
self
|
28
|
+
else
|
29
|
+
raise ArgumentError, "cannot filter_to_type for type '#{typ}'"
|
30
|
+
end
|
31
|
+
end
|
15
32
|
end
|
data/lib/fat_table/column.rb
CHANGED
@@ -196,7 +196,7 @@ module FatTable
|
|
196
196
|
if type == 'String'
|
197
197
|
items.reject(&:blank?).first
|
198
198
|
else
|
199
|
-
items.
|
199
|
+
items.filter_to_type(type).first
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
@@ -207,7 +207,7 @@ module FatTable
|
|
207
207
|
if type == 'String'
|
208
208
|
items.reject(&:blank?).last
|
209
209
|
else
|
210
|
-
items.
|
210
|
+
items.filter_to_type(type).last
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
@@ -219,7 +219,7 @@ module FatTable
|
|
219
219
|
if type == 'String'
|
220
220
|
items.reject(&:blank?).count.to_d
|
221
221
|
else
|
222
|
-
items.
|
222
|
+
items.filter_to_type(type).count.to_d
|
223
223
|
end
|
224
224
|
end
|
225
225
|
|
@@ -232,7 +232,7 @@ module FatTable
|
|
232
232
|
if type == 'String'
|
233
233
|
items.reject(&:blank?).min
|
234
234
|
else
|
235
|
-
items.
|
235
|
+
items.filter_to_type(type).min
|
236
236
|
end
|
237
237
|
end
|
238
238
|
|
@@ -245,7 +245,7 @@ module FatTable
|
|
245
245
|
if type == 'String'
|
246
246
|
items.reject(&:blank?).max
|
247
247
|
else
|
248
|
-
items.
|
248
|
+
items.filter_to_type(type).max
|
249
249
|
end
|
250
250
|
end
|
251
251
|
|
@@ -268,7 +268,7 @@ module FatTable
|
|
268
268
|
if type == 'String'
|
269
269
|
items.reject(&:blank?).join(' ')
|
270
270
|
else
|
271
|
-
items.
|
271
|
+
items.filter_to_type(type).sum
|
272
272
|
end
|
273
273
|
end
|
274
274
|
|
@@ -280,7 +280,7 @@ module FatTable
|
|
280
280
|
# average back to a DateTime.
|
281
281
|
def avg
|
282
282
|
only_with('avg', 'DateTime', 'Numeric')
|
283
|
-
itms = items.
|
283
|
+
itms = items.filter_to_type(type)
|
284
284
|
size = itms.size.to_d
|
285
285
|
if type == 'DateTime'
|
286
286
|
avg_jd = itms.map(&:jd).sum / size
|
@@ -301,9 +301,9 @@ module FatTable
|
|
301
301
|
only_with('var', 'DateTime', 'Numeric')
|
302
302
|
all_items =
|
303
303
|
if type == 'DateTime'
|
304
|
-
items.
|
304
|
+
items.filter_to_type(type).map(&:jd)
|
305
305
|
else
|
306
|
-
items.
|
306
|
+
items.filter_to_type(type)
|
307
307
|
end
|
308
308
|
n = count
|
309
309
|
return BigDecimal('0.0') if n <= 1
|
@@ -324,7 +324,7 @@ module FatTable
|
|
324
324
|
# number and computes the variance of those numbers.
|
325
325
|
def pvar
|
326
326
|
only_with('var', 'DateTime', 'Numeric')
|
327
|
-
n = items.
|
327
|
+
n = items.filter_to_type(type).size.to_d
|
328
328
|
return BigDecimal('0.0') if n <= 1
|
329
329
|
var * ((n - 1) / n)
|
330
330
|
end
|
@@ -361,7 +361,7 @@ module FatTable
|
|
361
361
|
# false. Works only with boolean Columns.
|
362
362
|
def any?
|
363
363
|
only_with('any?', 'Boolean')
|
364
|
-
items.
|
364
|
+
items.filter_to_type(type).any?
|
365
365
|
end
|
366
366
|
|
367
367
|
# :category: Aggregates
|
@@ -370,7 +370,7 @@ module FatTable
|
|
370
370
|
# false. Works only with boolean Columns.
|
371
371
|
def all?
|
372
372
|
only_with('all?', 'Boolean')
|
373
|
-
items.
|
373
|
+
items.filter_to_type(type).all?
|
374
374
|
end
|
375
375
|
|
376
376
|
# :category: Aggregates
|
@@ -379,7 +379,7 @@ module FatTable
|
|
379
379
|
# false. Works only with boolean Columns.
|
380
380
|
def none?
|
381
381
|
only_with('none?', 'Boolean')
|
382
|
-
items.
|
382
|
+
items.filter_to_type(type).none?
|
383
383
|
end
|
384
384
|
|
385
385
|
# :category: Aggregates
|
@@ -388,7 +388,7 @@ module FatTable
|
|
388
388
|
# otherwise return false. Works only with boolean Columns.
|
389
389
|
def one?
|
390
390
|
only_with('one?', 'Boolean')
|
391
|
-
items.
|
391
|
+
items.filter_to_type(type).one?
|
392
392
|
end
|
393
393
|
|
394
394
|
private
|
@@ -413,11 +413,10 @@ module FatTable
|
|
413
413
|
# a tolerant column, respond to type errors by converting the column to a
|
414
414
|
# String type.
|
415
415
|
def <<(itm)
|
416
|
-
items <<
|
416
|
+
items << convert_and_set_type(itm)
|
417
417
|
rescue IncompatibleTypeError => ex
|
418
418
|
if tolerant?
|
419
|
-
|
420
|
-
retry
|
419
|
+
items << Convert.convert_to_string(itm)
|
421
420
|
else
|
422
421
|
raise ex
|
423
422
|
end
|
@@ -436,9 +435,9 @@ module FatTable
|
|
436
435
|
|
437
436
|
private
|
438
437
|
|
439
|
-
def
|
440
|
-
new_val = Convert.convert_to_type(val, type)
|
441
|
-
if new_val && type == 'NilClass'
|
438
|
+
def convert_and_set_type(val)
|
439
|
+
new_val = Convert.convert_to_type(val, type, tolerant: tolerant?)
|
440
|
+
if new_val && (type == 'NilClass' || type == 'String')
|
442
441
|
@type =
|
443
442
|
if [true, false].include?(new_val)
|
444
443
|
'Boolean'
|
data/lib/fat_table/convert.rb
CHANGED
@@ -10,7 +10,7 @@ module FatTable
|
|
10
10
|
# determined, raise an error if the val cannot be converted to the Column
|
11
11
|
# type. Otherwise, returns the converted val as an object of the correct
|
12
12
|
# class.
|
13
|
-
def self.convert_to_type(val, type)
|
13
|
+
def self.convert_to_type(val, type, tolerant: false)
|
14
14
|
case type
|
15
15
|
when 'NilClass'
|
16
16
|
if val != false && val.blank?
|
@@ -66,6 +66,19 @@ module FatTable
|
|
66
66
|
when 'String'
|
67
67
|
if val.nil?
|
68
68
|
nil
|
69
|
+
elsif tolerant
|
70
|
+
# Allow String to upgrade to one of Numeric, DateTime, or Boolean if
|
71
|
+
# possible.
|
72
|
+
if (new_val = convert_to_numeric(val))
|
73
|
+
new_val
|
74
|
+
elsif (new_val = convert_to_date_time(val))
|
75
|
+
new_val
|
76
|
+
elsif (new_val = convert_to_boolean(val))
|
77
|
+
new_val
|
78
|
+
else
|
79
|
+
new_val = convert_to_string(val)
|
80
|
+
end
|
81
|
+
new_val
|
69
82
|
else
|
70
83
|
new_val = convert_to_string(val)
|
71
84
|
if new_val.nil?
|
data/lib/fat_table/evaluator.rb
CHANGED
@@ -45,17 +45,15 @@ module FatTable
|
|
45
45
|
end
|
46
46
|
|
47
47
|
# Return the result of evaluating +expr+ as a Ruby expression in which the
|
48
|
-
# instance variables set in Evaluator.new and any local variables set in
|
49
|
-
# Hash parameter +locals+ are available to the expression.
|
48
|
+
# instance variables set in Evaluator.new and any local variables set in
|
49
|
+
# the Hash parameter +locals+ are available to the expression. Certain
|
50
|
+
# errors simply return nil as the result. This can happen, for example,
|
51
|
+
# when a string gets into an otherwise numeric column because the column
|
52
|
+
# is set to tolerant.
|
50
53
|
def evaluate(expr = '', locals: {})
|
51
54
|
eval(expr, local_vars(binding, locals))
|
52
55
|
rescue NoMethodError, TypeError => ex
|
53
|
-
|
54
|
-
# Likely one of the locals was nil, so let nil be the result.
|
55
|
-
return nil
|
56
|
-
else
|
57
|
-
raise ex
|
58
|
-
end
|
56
|
+
nil
|
59
57
|
end
|
60
58
|
|
61
59
|
private
|
@@ -562,20 +562,21 @@ module FatTable
|
|
562
562
|
end
|
563
563
|
end
|
564
564
|
|
565
|
-
# Merge in formatting for column h based on the column
|
566
|
-
#
|
565
|
+
# Merge in formatting instructions for column h based on the column
|
566
|
+
# name, or if there is no formatting instructions for the column by
|
567
|
+
# name, merge in the formatting instructions based on the column's
|
568
|
+
# type. Insist on only the string type for the header location.
|
567
569
|
typ = (location == :header ? :string : table.type(h).as_sym)
|
568
570
|
parse_typ_method_name = 'parse_' + typ.to_s + '_fmt'
|
569
|
-
if fmts.key?(typ)
|
570
|
-
# Merge in type-based formatting
|
571
|
-
typ_fmt = send(parse_typ_method_name, fmts[typ]).first
|
572
|
-
format_h = format_h.merge(typ_fmt)
|
573
|
-
end
|
574
571
|
if fmts[h]
|
575
572
|
# Merge in column formatting
|
576
573
|
col_fmt = send(parse_typ_method_name, fmts[h],
|
577
574
|
strict: location != :header).first
|
578
575
|
format_h = format_h.merge(col_fmt)
|
576
|
+
elsif fmts.key?(typ)
|
577
|
+
# Merge in type-based formatting
|
578
|
+
typ_fmt = send(parse_typ_method_name, fmts[typ]).first
|
579
|
+
format_h = format_h.merge(typ_fmt)
|
579
580
|
end
|
580
581
|
|
581
582
|
# Copy :body formatting for column h to :bfirst and :gfirst if they
|
data/lib/fat_table/table.rb
CHANGED
@@ -779,7 +779,6 @@ module FatTable
|
|
779
779
|
last_key = nil
|
780
780
|
new_rows.each_with_index do |nrow, k|
|
781
781
|
new_tab << nrow
|
782
|
-
# key = nrow.fetch_values(*sort_heads)
|
783
782
|
key = nrow.fetch_values(*key_hash.keys)
|
784
783
|
new_tab.mark_boundary(k - 1) if last_key && key != last_key
|
785
784
|
last_key = key
|
@@ -1712,11 +1711,19 @@ module FatTable
|
|
1712
1711
|
end
|
1713
1712
|
|
1714
1713
|
# The <=> operator cannot handle nils without some help. Treat a nil as
|
1715
|
-
# smaller than any other value, but equal to other nils. The two keys are
|
1716
|
-
# compared with <=>.
|
1714
|
+
# smaller than any other value, but equal to other nils. The two keys are
|
1715
|
+
# assumed to be arrays of values to be compared with <=>. Since
|
1716
|
+
# tolerant_columns permit strings to be mixed in with columns of type
|
1717
|
+
# Numeric, DateTime, and Boolean, treat strings mixed with another type
|
1718
|
+
# the same as nils.
|
1717
1719
|
def compare_with_nils(key1, key2)
|
1718
1720
|
result = nil
|
1719
1721
|
key1.zip(key2) do |k1, k2|
|
1722
|
+
if k1.is_a?(String) && !k2.is_a?(String)
|
1723
|
+
k1 = nil
|
1724
|
+
elsif !k1.is_a?(String) && k2.is_a?(String)
|
1725
|
+
k2 = nil
|
1726
|
+
end
|
1720
1727
|
if k1.nil? && k2.nil?
|
1721
1728
|
result = 0
|
1722
1729
|
next
|
data/lib/fat_table/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fat_table
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel E. Doherty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|