fat_table 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|