fat_table 0.5.1 → 0.5.2
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 +10 -0
- data/lib/fat_table/table.rb +88 -55
- 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: f35f99181e39d7569ce7df958ae92742617826e54b8ed2c6352b73c5723a3d44
|
4
|
+
data.tar.gz: d37acb3f0be27191bafa17ae30b51dfd2db2c4a5d97e6c80fa5399f2618ea98b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eafd2077939c57673358a680490ccbe48218e8b290540790f3526b5945337e53c9366369c255adcc85e01916ad012cbad12132593def15350fd3993304bc5a30
|
7
|
+
data.tar.gz: e7a542986752ac4f632e7344c49080786e0e52ecbe224a0644a6da7b4ec65dd8ca2b9abe842ee295ad7cf19a7a0ccd0e93b22632716c95533665a21d14b5cc83
|
data/README.org
CHANGED
@@ -81,6 +81,8 @@ org-mode buffer as an org-table, ready for processing by other code blocks.
|
|
81
81
|
- [[#from-arrays-of-hashes][From Arrays of Hashes]]
|
82
82
|
- [[#from-sql-queries][From SQL queries]]
|
83
83
|
- [[#marking-groups-in-input][Marking Groups in Input]]
|
84
|
+
- [[#manually][Manually]]
|
85
|
+
- [[#when-reading-in-tables][When Reading in Tables]]
|
84
86
|
- [[#accessing-parts-of-tables][Accessing Parts of Tables]]
|
85
87
|
- [[#rows][Rows]]
|
86
88
|
- [[#columns-1][Columns]]
|
@@ -861,6 +863,14 @@ creates will be used for all subsequent ~.from_sql~ calls until ~.connect~ is
|
|
861
863
|
called again.
|
862
864
|
|
863
865
|
*** Marking Groups in Input
|
866
|
+
**** Manually
|
867
|
+
At any point, you can add a boundary to a table by invokong the
|
868
|
+
~mark_boundary~ method. Without an argument, it adds the boundary to the end
|
869
|
+
of the table; with a numeric argument, ~n~, it adds the boundary after row
|
870
|
+
~n~.
|
871
|
+
|
872
|
+
**** When Reading in Tables
|
873
|
+
|
864
874
|
~FatTable~ tables has a concept of "groups" of rows that play a role in many of
|
865
875
|
the methods for operating on them as explained [[Groups][below]].
|
866
876
|
|
data/lib/fat_table/table.rb
CHANGED
@@ -53,7 +53,14 @@ module FatTable
|
|
53
53
|
class Table
|
54
54
|
# An Array of FatTable::Columns that constitute the table.
|
55
55
|
attr_reader :columns
|
56
|
-
|
56
|
+
|
57
|
+
# Record boundaries set explicitly with mark_boundaries or from reading
|
58
|
+
# hlines from input. When we want to access boundaries, however, we want
|
59
|
+
# to add an implict boundary at the last row of the table. Since, as the
|
60
|
+
# table grows, the implict boundary changes index, we synthesize the
|
61
|
+
# boundaries by dynamically adding the final boundary with the #boundaries
|
62
|
+
# method call.
|
63
|
+
attr_accessor :explicit_boundaries
|
57
64
|
|
58
65
|
###########################################################################
|
59
66
|
# Constructors
|
@@ -64,7 +71,7 @@ module FatTable
|
|
64
71
|
# Return an empty FatTable::Table object.
|
65
72
|
def initialize(*heads)
|
66
73
|
@columns = []
|
67
|
-
@
|
74
|
+
@explicit_boundaries = []
|
68
75
|
unless heads.empty?
|
69
76
|
heads.each do |h|
|
70
77
|
@columns << Column.new(header: h)
|
@@ -84,11 +91,10 @@ module FatTable
|
|
84
91
|
|
85
92
|
def __empty!
|
86
93
|
@columns = []
|
87
|
-
@
|
94
|
+
@explicit_boundaries = []
|
88
95
|
self
|
89
96
|
end
|
90
97
|
|
91
|
-
|
92
98
|
# :category: Constructors
|
93
99
|
|
94
100
|
# Construct a Table from the contents of a CSV file named +fname+. Headers
|
@@ -454,8 +460,6 @@ module FatTable
|
|
454
460
|
# large table, that would require that we construct all the rows for a range
|
455
461
|
# of any size.
|
456
462
|
def rows_range(first = 0, last = nil) # :nodoc:
|
457
|
-
last ||= size - 1
|
458
|
-
last = [last, 0].max
|
459
463
|
raise UserError, 'first must be <= last' unless first <= last
|
460
464
|
|
461
465
|
rows = []
|
@@ -501,6 +505,8 @@ module FatTable
|
|
501
505
|
# the headers from the body) marks a boundary for the row immediately
|
502
506
|
# preceding the hline.
|
503
507
|
#
|
508
|
+
# Boundaries can also be added manually with the +mark_boundary+ method.
|
509
|
+
#
|
504
510
|
# The #order_by method resets the boundaries then adds boundaries at the
|
505
511
|
# last row of each group of rows on which the sort keys were equal as a
|
506
512
|
# boundary.
|
@@ -536,7 +542,7 @@ module FatTable
|
|
536
542
|
|
537
543
|
# Return the number of groups in the table.
|
538
544
|
def number_of_groups
|
539
|
-
boundaries.size
|
545
|
+
empty? ? 0 : boundaries.size
|
540
546
|
end
|
541
547
|
|
542
548
|
# Return the range of row indexes for boundary number +k+
|
@@ -546,17 +552,13 @@ module FatTable
|
|
546
552
|
raise ArgumentError, "boundary number '#{k}' out of range in boundary_row_range"
|
547
553
|
end
|
548
554
|
|
549
|
-
if boundaries.
|
550
|
-
(0..size-1)
|
551
|
-
elsif boundaries.size == 1
|
555
|
+
if boundaries.size == 1
|
552
556
|
(0..boundaries.first)
|
553
|
-
|
557
|
+
elsif k.zero?
|
554
558
|
# Keep index at or above zero
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
(boundaries[k-1]+1..boundaries[k])
|
559
|
-
end
|
559
|
+
(0..boundaries[k])
|
560
|
+
else
|
561
|
+
((boundaries[k - 1] + 1)..boundaries[k])
|
560
562
|
end
|
561
563
|
end
|
562
564
|
|
@@ -581,19 +583,32 @@ module FatTable
|
|
581
583
|
# the groups displayed in the output. This modifies the input table, so is a
|
582
584
|
# departure from the otherwise immutability of Tables.
|
583
585
|
def degroup!
|
584
|
-
|
586
|
+
self.explicit_boundaries = []
|
585
587
|
self
|
586
588
|
end
|
587
589
|
|
588
590
|
# Mark a group boundary at row +row+, and if +row+ is +nil+, mark the last
|
589
|
-
# row in the table as a group boundary.
|
590
|
-
#
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
591
|
+
# row in the table as a group boundary. An attempt to add a boundary to
|
592
|
+
# an empty table has no effect. We adopt the convention that the last row
|
593
|
+
# of the table always marks an implicit boundary even if it is not in the
|
594
|
+
# @explicit_boundaries array. When we "mark" a boundary, we intend it to
|
595
|
+
# be an explicit boundary, even if it marks the last row of the table.
|
596
|
+
def mark_boundary(row_num = nil)
|
597
|
+
return self if empty?
|
598
|
+
|
599
|
+
if row_num
|
600
|
+
unless row_num < size
|
601
|
+
raise ArgumentError, "can't mark boundary at row #{row_num}, last row is #{size - 1}"
|
602
|
+
end
|
603
|
+
unless row_num >= 0
|
604
|
+
raise ArgumentError, "can't mark boundary at non-positive row #{row_num}"
|
605
|
+
end
|
606
|
+
explicit_boundaries.push(row_num)
|
607
|
+
elsif size > 0
|
608
|
+
explicit_boundaries.push(size - 1)
|
596
609
|
end
|
610
|
+
normalize_boundaries
|
611
|
+
self
|
597
612
|
end
|
598
613
|
|
599
614
|
# :stopdoc:
|
@@ -601,10 +616,21 @@ module FatTable
|
|
601
616
|
# Make sure size - 1 is last boundary and that they are unique and sorted.
|
602
617
|
def normalize_boundaries
|
603
618
|
unless empty?
|
604
|
-
|
605
|
-
|
619
|
+
self.explicit_boundaries = explicit_boundaries.uniq.sort
|
620
|
+
end
|
621
|
+
explicit_boundaries
|
622
|
+
end
|
623
|
+
|
624
|
+
# Return the explicit_boundaries, augmented by an implicit boundary for
|
625
|
+
# the end of the table, unless it's already an implicit boundary.
|
626
|
+
def boundaries
|
627
|
+
return [] if empty?
|
628
|
+
|
629
|
+
if explicit_boundaries.last == size - 1
|
630
|
+
explicit_boundaries
|
631
|
+
else
|
632
|
+
explicit_boundaries + [size - 1]
|
606
633
|
end
|
607
|
-
boundaries
|
608
634
|
end
|
609
635
|
|
610
636
|
protected
|
@@ -613,24 +639,43 @@ module FatTable
|
|
613
639
|
# increase each of the indexes in bounds by shift. This is used in the
|
614
640
|
# #union_all method.
|
615
641
|
def append_boundaries(bounds, shift: 0)
|
616
|
-
@
|
642
|
+
@explicit_boundaries += bounds.map { |k| k + shift }
|
617
643
|
end
|
618
644
|
|
619
|
-
# Return the group number to which row ~
|
620
|
-
# user's point of view are indexed starting at
|
621
|
-
def row_index_to_group_index(
|
645
|
+
# Return the group number to which row ~row_num~ belongs. Groups, from the
|
646
|
+
# user's point of view are indexed starting at 0.
|
647
|
+
def row_index_to_group_index(row_num)
|
622
648
|
boundaries.each_with_index do |b_last, g_num|
|
623
|
-
return (g_num + 1) if
|
649
|
+
return (g_num + 1) if row_num <= b_last
|
650
|
+
end
|
651
|
+
0
|
652
|
+
end
|
653
|
+
|
654
|
+
# Return the index of the first row in group number +grp_num+
|
655
|
+
def first_row_num_in_group(grp_num)
|
656
|
+
if grp_num >= boundaries.size || grp_num < 0
|
657
|
+
raise ArgumentError, "group number #{grp_num} out of bounds"
|
624
658
|
end
|
625
|
-
|
659
|
+
|
660
|
+
grp_num.zero? ? 0 : boundaries[grp_num - 1] + 1
|
626
661
|
end
|
627
662
|
|
628
|
-
|
663
|
+
# Return the index of the last row in group number +grp_num+
|
664
|
+
def last_row_num_in_group(grp_num)
|
665
|
+
if grp_num > boundaries.size || grp_num < 0
|
666
|
+
raise ArgumentError, "group number #{grp_num} out of bounds"
|
667
|
+
else
|
668
|
+
boundaries[grp_num]
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
# Return the rows for group number +grp_num+.
|
673
|
+
def group_rows(grp_num) # :nodoc:
|
629
674
|
normalize_boundaries
|
630
|
-
return [] unless
|
675
|
+
return [] unless grp_num < boundaries.size
|
631
676
|
|
632
|
-
first =
|
633
|
-
last =
|
677
|
+
first = first_row_num_in_group(grp_num)
|
678
|
+
last = last_row_num_in_group(grp_num)
|
634
679
|
rows_range(first, last)
|
635
680
|
end
|
636
681
|
|
@@ -876,7 +921,7 @@ module FatTable
|
|
876
921
|
ev.eval_after_hook(locals: new_row)
|
877
922
|
result << new_row
|
878
923
|
end
|
879
|
-
result.
|
924
|
+
result.explicit_boundaries = explicit_boundaries
|
880
925
|
result.normalize_boundaries
|
881
926
|
result
|
882
927
|
end
|
@@ -1013,8 +1058,6 @@ module FatTable
|
|
1013
1058
|
set_operation(other, :difference, distinct: false)
|
1014
1059
|
end
|
1015
1060
|
|
1016
|
-
public
|
1017
|
-
|
1018
1061
|
# An Array of symbols for the valid join types.
|
1019
1062
|
JOIN_TYPES = %i[inner left right full cross].freeze
|
1020
1063
|
|
@@ -1123,14 +1166,14 @@ module FatTable
|
|
1123
1166
|
type: join_type)
|
1124
1167
|
result << out_row
|
1125
1168
|
end
|
1126
|
-
next unless
|
1169
|
+
next unless [:left, :full].include?(join_type)
|
1127
1170
|
next if self_row_matched
|
1128
1171
|
|
1129
1172
|
result << build_out_row(row_a: self_row,
|
1130
1173
|
row_b: other_row_nils,
|
1131
1174
|
type: join_type)
|
1132
1175
|
end
|
1133
|
-
if
|
1176
|
+
if [:right, :full].include?(join_type)
|
1134
1177
|
other_rows.each_with_index do |other_row, k|
|
1135
1178
|
next if other_row_matches[k]
|
1136
1179
|
|
@@ -1259,7 +1302,7 @@ module FatTable
|
|
1259
1302
|
partial_result = nil
|
1260
1303
|
else
|
1261
1304
|
# First of a pair of _a or _b
|
1262
|
-
partial_result =
|
1305
|
+
partial_result = +"(#{a_head}_a == "
|
1263
1306
|
end
|
1264
1307
|
last_sym = a_head
|
1265
1308
|
when /\A(?<sy>.*)_b\z/
|
@@ -1278,7 +1321,7 @@ module FatTable
|
|
1278
1321
|
partial_result = nil
|
1279
1322
|
else
|
1280
1323
|
# First of a pair of _a or _b
|
1281
|
-
partial_result =
|
1324
|
+
partial_result = +"(#{b_head}_b == "
|
1282
1325
|
end
|
1283
1326
|
b_common_heads << b_head
|
1284
1327
|
last_sym = b_head
|
@@ -1385,15 +1428,6 @@ module FatTable
|
|
1385
1428
|
|
1386
1429
|
# :category: Constructors
|
1387
1430
|
|
1388
|
-
# Add a group boundary mark at the given row, or at the end of the table
|
1389
|
-
# by default.
|
1390
|
-
def add_boundary(at_row = nil)
|
1391
|
-
row = at_row || (size - 1)
|
1392
|
-
@boundaries << row
|
1393
|
-
end
|
1394
|
-
|
1395
|
-
# :category: Constructors
|
1396
|
-
|
1397
1431
|
# Add a +row+ represented by a Hash having the headers as keys. If +mark:+
|
1398
1432
|
# is set true, mark this row as a boundary. All tables should be built
|
1399
1433
|
# ultimately using this method as a primitive.
|
@@ -1603,8 +1637,7 @@ module FatTable
|
|
1603
1637
|
result.mark_boundary if k == size - 1 && add_boundaries
|
1604
1638
|
end
|
1605
1639
|
if inherit_boundaries
|
1606
|
-
result.
|
1607
|
-
other.normalize_boundaries
|
1640
|
+
result.explicit_boundaries = boundaries
|
1608
1641
|
result.append_boundaries(other.boundaries, shift: size)
|
1609
1642
|
end
|
1610
1643
|
result.normalize_boundaries
|
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.2
|
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-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|