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