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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68369046961f41a0a22139e3b1b3f9f3465fc6e5e661d36f9ed09ab60d4fc99e
4
- data.tar.gz: 5ae22c1c1e40735f13734366172aa6aae66102c492d4911f8dd370a6fa29cf15
3
+ metadata.gz: f35f99181e39d7569ce7df958ae92742617826e54b8ed2c6352b73c5723a3d44
4
+ data.tar.gz: d37acb3f0be27191bafa17ae30b51dfd2db2c4a5d97e6c80fa5399f2618ea98b
5
5
  SHA512:
6
- metadata.gz: 470727e6d9afc2ed93658fecc7cab7c36f6b14a28d4682aeb8d54153058591e39a02f77ea9d8966b6d857ca1c463479350adc11e63952fde8404e2f9b614f3e4
7
- data.tar.gz: f13f33a01c5106c8b8a877fa61b16c1b32179a49c67fe7d542f339a384cbfc437037ac567d96cbb9e4f78e046ae46832e60d8f7d57313d95bf9b70778481f847
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
 
@@ -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
- attr_accessor :boundaries
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
- @boundaries = []
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
- @boundaries = []
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.empty?
550
- (0..size-1)
551
- elsif boundaries.size == 1
555
+ if boundaries.size == 1
552
556
  (0..boundaries.first)
553
- else
557
+ elsif k.zero?
554
558
  # Keep index at or above zero
555
- if k.zero?
556
- (0..boundaries[k])
557
- else
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
- @boundaries = []
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. This is mainly used for internal
590
- # purposes.
591
- def mark_boundary(row = nil) # :nodoc:
592
- if row
593
- boundaries.push(row)
594
- else
595
- boundaries.push(size - 1)
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
- boundaries.push(size - 1) unless boundaries.include?(size - 1)
605
- self.boundaries = boundaries.uniq.sort
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
- @boundaries += bounds.map { |k| k + shift }
642
+ @explicit_boundaries += bounds.map { |k| k + shift }
617
643
  end
618
644
 
619
- # Return the group number to which row ~row~ belongs. Groups, from the
620
- # user's point of view are indexed starting at 1.
621
- def row_index_to_group_index(row)
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 row <= b_last
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
- 1
659
+
660
+ grp_num.zero? ? 0 : boundaries[grp_num - 1] + 1
626
661
  end
627
662
 
628
- def group_rows(row) # :nodoc:
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 row < boundaries.size
675
+ return [] unless grp_num < boundaries.size
631
676
 
632
- first = row.zero? ? 0 : boundaries[row - 1] + 1
633
- last = boundaries[row]
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.boundaries = boundaries
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 %i[left full].include?(join_type)
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 %i[right full].include?(join_type)
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 = String.new("(#{a_head}_a == ")
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 = String.new("(#{b_head}_b == ")
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.boundaries = normalize_boundaries
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module FatTable
4
4
  # The current version of FatTable
5
- VERSION = '0.5.1'
5
+ VERSION = '0.5.2'
6
6
  end
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.1
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-21 00:00:00.000000000 Z
11
+ date: 2022-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler