fat_core 1.5.0 → 1.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8f9197b29ac69c96409642ef86bb5a5bf3fdace
4
- data.tar.gz: 6aeb17344e346ebfc21030523929036934eee6a4
3
+ metadata.gz: f6d9999db399e323a385070ca59d15deb692d65d
4
+ data.tar.gz: 5bb8ade666435e0c67afeaa293e236082cb19906
5
5
  SHA512:
6
- metadata.gz: 3800832b0339a3c9deca6450bece102d33dc0a7912b18e9a0c743b85b438ba076bf1b290f70b0bd3a8d0fb48f65780be8375175d54aa50bd48fdf8dee89b05b3
7
- data.tar.gz: 914b7895346e3a07422027e54b3ae11bdd5bed6297b3281488a93bd3e9a8d2b29efd7550b6510f32ec47c2bd5cd174762595f3f22b055ea0245f63de1de9d065
6
+ metadata.gz: 806ba3e817c5899bd5cb3ffa7a13069d8710c2a29406ae9b6060cf2d30e5d28cc3fc1b983d8b8b3aa9beafc6ceab505695a218c39e8e605ec811bc0c671a3bf7
7
+ data.tar.gz: e11602a00d01b81bd201092b4bf3cbe8780435d2da3bd3f708f83b2e94677e43a2993b0fc4066fdf8d5d45b258e2516c928c72790e93e84dc77f64714b202f59
@@ -227,21 +227,99 @@ module FatCore
227
227
  result
228
228
  end
229
229
 
230
- # Return a Table that combines this table with another table. The headers of
231
- # this table are used in the result. There must be the same number of
232
- # columns of the same type in the two tables, or an exception will be
233
- # thrown. Unlike in SQL, no duplicates are eliminated from the result.
230
+ # Return this table with all duplicate rows eliminated.
231
+ def distinct
232
+ result = Table.new
233
+ uniq_rows = rows.uniq
234
+ uniq_rows.each do |row|
235
+ result << row
236
+ end
237
+ result
238
+ end
239
+
240
+ def uniq
241
+ distinct
242
+ end
243
+
244
+ # Return a Table that combines this table with another table. In other
245
+ # words, return the union of this table with the other. The headers of this
246
+ # table are used in the result. There must be the same number of columns of
247
+ # the same type in the two tables, or an exception will be thrown.
248
+ # Duplicates are eliminated from the result.
234
249
  def union(other)
250
+ set_operation(other, :+, true)
251
+ end
252
+
253
+ # Return a Table that combines this table with another table. In other
254
+ # words, return the union of this table with the other. The headers of this
255
+ # table are used in the result. There must be the same number of columns of
256
+ # the same type in the two tables, or an exception will be thrown.
257
+ # Duplicates are not eliminated from the result.
258
+ def union_all(other)
259
+ set_operation(other, :+, false)
260
+ end
261
+
262
+ # Return a Table that includes the rows that appear in this table and in
263
+ # another table. In other words, return the intersection of this table with
264
+ # the other. The headers of this table are used in the result. There must be
265
+ # the same number of columns of the same type in the two tables, or an
266
+ # exception will be thrown. Duplicates are eliminated from the result.
267
+ def intersect(other)
268
+ set_operation(other, :intersect, true)
269
+ end
270
+
271
+ # Return a Table that includes the rows that appear in this table and in
272
+ # another table. In other words, return the intersection of this table with
273
+ # the other. The headers of this table are used in the result. There must be
274
+ # the same number of columns of the same type in the two tables, or an
275
+ # exception will be thrown. Duplicates are not eliminated from the result.
276
+ def intersect_all(other)
277
+ set_operation(other, :intersect, false)
278
+ end
279
+
280
+ # Return a Table that includes the rows of this table except for any rows
281
+ # that are the same as those in another table. In other words, return the
282
+ # set difference between this table an the other. The headers of this table
283
+ # are used in the result. There must be the same number of columns of the
284
+ # same type in the two tables, or an exception will be thrown. Duplicates
285
+ # are eliminated from the result.
286
+ def except(other)
287
+ set_operation(other, :difference, true)
288
+ end
289
+
290
+ # Return a Table that includes the rows of this table except for any rows
291
+ # that are the same as those in another table. In other words, return the
292
+ # set difference between this table an the other. The headers of this table
293
+ # are used in the result. There must be the same number of columns of the
294
+ # same type in the two tables, or an exception will be thrown. Duplicates
295
+ # are not eliminated from the result.
296
+ def except_all(other)
297
+ set_operation(other, :difference, false)
298
+ end
299
+
300
+ private
301
+
302
+ # Apply the set operation given by op between this table and the other table
303
+ # given in the first argument. If distinct is true, eliminate duplicates
304
+ # from the result.
305
+ def set_operation(other, op = :+, distinct = true)
235
306
  unless columns.size == other.columns.size
236
- raise 'Cannot apply union to tables with a different number of columns.'
307
+ raise 'Cannot apply a set operation to tables with a different number of columns.'
308
+ end
309
+ unless columns.map(&:type) == other.columns.map(&:type)
310
+ raise 'Cannot apply a set operation to tables with different column types.'
237
311
  end
312
+ other_rows = other.rows.map { |r| r.replace_keys(headers) }
238
313
  result = Table.new
239
- columns.each_with_index do |col, k|
240
- result.add_column(col + other.columns[k])
314
+ new_rows = rows.send(op, other_rows)
315
+ new_rows.each do |row|
316
+ result << row
241
317
  end
242
- result
318
+ distinct ? result.distinct : result
243
319
  end
244
320
 
321
+ public
322
+
245
323
  # Return a table that joins this table to another based on one or more join
246
324
  # expressions. There are several possibilities for the join expressions:
247
325
  #
@@ -1,7 +1,7 @@
1
1
  module FatCore
2
2
  MAJOR = 1
3
3
  MINOR = 5
4
- PATCH = 0
4
+ PATCH = 1
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
7
7
  end
@@ -519,6 +519,61 @@ EOS
519
519
  end
520
520
  end
521
521
 
522
+ describe 'union' do
523
+ it 'should be able to union with a compatible table' do
524
+ aoh = [
525
+ { a: '5', 'Two words' => '20', c: '3,123', d: 'apple' },
526
+ { a: '4', 'Two words' => '5', c: 6412, d: 'orange' },
527
+ { a: '7', 'Two words' => '8', c: '$1,888', d: 'apple' }
528
+ ]
529
+ tab1 = Table.new(aoh)
530
+ aoh2 = [
531
+ { t: '8', 'Two worlds' => '65', s: '5,143', u: 'kiwi' },
532
+ { t: '87', 'Two worlds' => '12', s: 412, u: 'banana' },
533
+ { t: '13', 'Two worlds' => '11', s: '$1,821', u: 'grape' }
534
+ ]
535
+ tab2 = Table.new(aoh2)
536
+ utab = tab1.union(tab2)
537
+ expect(utab.rows.size).to eq(6)
538
+ end
539
+
540
+ it 'should throw an exception for union with different sized tables' do
541
+ aoh = [
542
+ { a: '5', 'Two words' => '20', c: '3,123' },
543
+ { a: '4', 'Two words' => '5', c: 6412 },
544
+ { a: '7', 'Two words' => '8', c: '$1,888' }
545
+ ]
546
+ tab1 = Table.new(aoh)
547
+ aoh2 = [
548
+ { t: '8', 'Two worlds' => '65', s: '5,143', u: 'kiwi' },
549
+ { t: '87', 'Two worlds' => '12', s: 412, u: 'banana' },
550
+ { t: '13', 'Two worlds' => '11', s: '$1,821', u: 'grape' }
551
+ ]
552
+ tab2 = Table.new(aoh2)
553
+ expect {
554
+ tab1.union(tab2)
555
+ }.to raise_error(/different number of columns/)
556
+ end
557
+
558
+ it 'should throw an exception for union with different types' do
559
+ aoh = [
560
+ { a: '5', 'Two words' => '20', s: '5143', c: '3123' },
561
+ { a: '4', 'Two words' => '5', s: 412, c: 6412 },
562
+ { a: '7', 'Two words' => '8', s: '$1821', c: '$1888' }
563
+ ]
564
+ tab1 = Table.new(aoh)
565
+ aoh2 = [
566
+ { t: '8', 'Two worlds' => '65', s: '2016-01-17', u: 'kiwi' },
567
+ { t: '87', 'Two worlds' => '12', s: Date.today, u: 'banana' },
568
+ { t: '13', 'Two worlds' => '11', s: '[2015-05-21]', u: 'grape' }
569
+ ]
570
+ tab2 = Table.new(aoh2)
571
+ expect {
572
+ tab1.union(tab2)
573
+ }.to raise_error(/different column types/)
574
+ end
575
+ end
576
+
522
577
  describe 'select' do
523
578
  it 'should be able to select by column names' do
524
579
  aoh = [
@@ -715,93 +770,6 @@ EOS
715
770
  end
716
771
  end
717
772
 
718
- describe 'set operations' do
719
- before :all do
720
- aoh = [
721
- { a: '5', 'Two words' => '20', c: '3,123', d: 'apple' },
722
- { a: '4', 'Two words' => '5', c: 6412, d: 'orange' },
723
- { a: '4', 'Two words' => '5', c: 6412, d: 'orange' },
724
- { a: '7', 'Two words' => '8', c: '$1,888', d: 'apple' }
725
- ]
726
- @tab1 = Table.new(aoh)
727
- aoh2 = [
728
- { t: '8', 'Two worlds' => '65', s: '5,143', u: 'kiwi' },
729
- { t: '87', 'Two worlds' => '12', s: 412, u: 'banana' },
730
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
731
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
732
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
733
- { t: '13', 'Two worlds' => '11', s: '$1,821', u: 'grape' }
734
- ]
735
- @tab2 = Table.new(aoh2)
736
- aoh2e = [
737
- { t: '8', 'Two worlds' => '65', s: '5,143', u: 'kiwi' },
738
- { t: '87', 'Two worlds' => '12', s: 412, u: 'banana' },
739
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
740
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
741
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
742
- { t: '4', 'Two worlds' => '5', s: 6412, u: 'orange' },
743
- { t: '13', 'Two worlds' => '11', s: '$1,821', u: 'grape' }
744
- ]
745
- @tab2e = Table.new(aoh2e)
746
- # Fewer columns
747
- aoh3 = [
748
- { a: '5', 'Two words' => '20', c: '3,123' },
749
- { a: '4', 'Two words' => '5', c: 6412 },
750
- { a: '7', 'Two words' => '8', c: '$1,888' }
751
- ]
752
- @tab3 = Table.new(aoh3)
753
- # Different types
754
- aoh4 = [
755
- { t: '8', 'Two worlds' => '65', s: '2016-01-17', u: 'kiwi' },
756
- { t: '87', 'Two worlds' => '12', s: Date.today, u: 'banana' },
757
- { t: '13', 'Two worlds' => '11', s: '[2015-05-21]', u: 'grape' }
758
- ]
759
- @tab4 = Table.new(aoh4)
760
- end
761
-
762
- it 'union' do
763
- utab = @tab1.union(@tab2)
764
- expect(utab.size).to eq(6)
765
- end
766
-
767
- it 'union_all' do
768
- utab = @tab1.union_all(@tab2)
769
- expect(utab.size).to eq(10)
770
- end
771
-
772
- it 'intersect' do
773
- utab = @tab1.intersect(@tab2)
774
- expect(utab.size).to eq(1)
775
- end
776
-
777
- it 'intersect_all' do
778
- utab = @tab1.intersect_all(@tab2)
779
- expect(utab.size).to eq(2)
780
- end
781
-
782
- it 'except' do
783
- utab = @tab2.except(@tab1)
784
- expect(utab.size).to eq(4)
785
- end
786
-
787
- it 'except_all' do
788
- utab = @tab2e.except_all(@tab1)
789
- expect(utab.size).to eq(5)
790
- end
791
-
792
- it 'should throw an exception for union with different sized tables' do
793
- expect {
794
- @tab1.union(@tab3)
795
- }.to raise_error(/different number of columns/)
796
- end
797
-
798
- it 'should throw an exception for union with different types' do
799
- expect {
800
- @tab1.union(@tab4)
801
- }.to raise_error(/different column types/)
802
- end
803
- end
804
-
805
773
  describe 'output' do
806
774
  it 'should be able to return itself as an array of arrays' do
807
775
  aoh = [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fat_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.1
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: 2017-03-02 00:00:00.000000000 Z
11
+ date: 2017-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov