fat_core 1.4.0 → 1.5.0

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
  SHA1:
3
- metadata.gz: b85c4931e6e06fcb0b7bf0359f67242fa06034b0
4
- data.tar.gz: fc263e3393af22aae09423a94430461f1c07d476
3
+ metadata.gz: d8f9197b29ac69c96409642ef86bb5a5bf3fdace
4
+ data.tar.gz: 6aeb17344e346ebfc21030523929036934eee6a4
5
5
  SHA512:
6
- metadata.gz: a69a5d129cc9135c87b628f45e1ca32869fca906bab23986ac4b0e93fb2bc75d52aaaf7b1da93828971b7d9fc9a5b8606c6daf45b22bcf3de976c5e68c90b639
7
- data.tar.gz: 15f2a2de60a73586a8c6c0b60f919a66dfd523f58a72adf55a995d93e2b13b52427b190e21a76ad3002567e47167ca44b88d162c04371c0a6f8613bbaafa60a1
6
+ metadata.gz: 3800832b0339a3c9deca6450bece102d33dc0a7912b18e9a0c743b85b438ba076bf1b290f70b0bd3a8d0fb48f65780be8375175d54aa50bd48fdf8dee89b05b3
7
+ data.tar.gz: 914b7895346e3a07422027e54b3ae11bdd5bed6297b3281488a93bd3e9a8d2b29efd7550b6510f32ec47c2bd5cd174762595f3f22b055ea0245f63de1de9d065
data/TODO.org CHANGED
@@ -1,10 +1,19 @@
1
1
  * Conversion to Spreadsheets
2
2
  This is a [[https://github.com/westonganger/spreadsheet_architect][gem]] that I can include into the Table model to convert a table into
3
3
  a spread-sheet, or even a sheet in a multi-sheet spreadsheet file.
4
+
4
5
  * Formatters
5
6
  Need to think about ways to define formatters for Table for different output
6
7
  types, including tty, color-tty, latex, csv, spreadsheet?
8
+
7
9
  * Add a Group Boundary concept
8
10
  If I want a table to perform sub-totals at various break points, need to have a
9
11
  way for a table to record its grouping boundaries. Maybe an array of row
10
12
  numbers? Automatically injected by the group-by method?
13
+
14
+ * DONE Add uniq method and set operations
15
+ CLOSED: [2017-03-02 Thu 15:54]
16
+ - State "WAIT" from "TODO" [2017-03-02 Thu 15:54]
17
+ - State "TODO" from [2017-03-02 Thu 15:54]
18
+ For tables, add a method that eliminates any duplicate rows. Perhaps just
19
+ apply Array#uniq to the columns?
@@ -2,4 +2,26 @@ class Array
2
2
  def last_i
3
3
  self.size - 1
4
4
  end
5
+
6
+ # Return a new array that is the intersection of this Array with other, but
7
+ # without removing duplicates as the :& method does.
8
+ def intersect(other)
9
+ result = []
10
+ each do |itm|
11
+ result << itm if other.include?(itm)
12
+ end
13
+ result
14
+ end
15
+
16
+ # Return an array that is the difference between this Array and the other, but
17
+ # without removing duplicates as the :- method does.
18
+ def difference(other)
19
+ result = deep_dup
20
+ other.each do |itm|
21
+ if (k = result.index(itm))
22
+ result.delete_at(k)
23
+ end
24
+ end
25
+ result
26
+ end
5
27
  end
data/lib/fat_core/hash.rb CHANGED
@@ -20,6 +20,7 @@ class Hash
20
20
  self
21
21
  end
22
22
 
23
+ # Change each key of this Hash to its value in key_map
23
24
  def remap_keys(key_map = {})
24
25
  new_hash = {}
25
26
  each_pair do |key, val|
@@ -31,4 +32,12 @@ class Hash
31
32
  end
32
33
  new_hash
33
34
  end
35
+
36
+ # Change the keys of this Hash to new_keys, an array of keys
37
+ def replace_keys(new_keys)
38
+ unless keys.size == new_keys.size
39
+ raise ArgumentError, 'replace_keys: new keys size differs from key size'
40
+ end
41
+ to_a.each_with_index.map { |(_k, v), i| [new_keys[i], v] }.to_h
42
+ end
34
43
  end
@@ -304,7 +304,7 @@ module FatCore
304
304
  # have N and M rows respectively, the joined table will have N * M
305
305
  # rows.
306
306
  #
307
- JOIN_TYPES = [ :inner, :left, :right, :full, :cross ]
307
+ JOIN_TYPES = [:inner, :left, :right, :full, :cross]
308
308
 
309
309
  def join(other, *exps, join_type: :inner)
310
310
  raise ArgumentError, 'need other table as first argument to join' unless other.is_a?(Table)
@@ -1,6 +1,6 @@
1
1
  module FatCore
2
2
  MAJOR = 1
3
- MINOR = 4
3
+ MINOR = 5
4
4
  PATCH = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
@@ -5,4 +5,20 @@ describe Array do
5
5
  letters = ('a'..'z').to_a
6
6
  expect(letters.last_i).to eq(25)
7
7
  end
8
+
9
+ it 'intersection' do
10
+ expect(%w(A A B A C A B).intersect(%w(A B A))).to eq(%w(A A B A A B))
11
+ expect(%w(A A B A C A B).intersect(%w(A B))).to eq(%w(A A B A A B))
12
+ expect(%w(A A B A C A B).intersect(%w(A))).to eq(%w(A A A A))
13
+ expect(%w(A A B A C A B).intersect(%w(B))).to eq(%w(B B))
14
+ expect(%w(A A B A C A B).intersect(%w(C))).to eq(%w(C))
15
+ end
16
+
17
+ it 'difference' do
18
+ expect(%w(A A B A C A B).difference(%w(A B A))).to eq(%w(A C A B))
19
+ expect(%w(A A B A C A B).difference(%w(A B))).to eq(%w(A A C A B))
20
+ expect(%w(A A B A C A B).difference(%w(A))).to eq(%w(A B A C A B))
21
+ expect(%w(A A B A C A B).difference(%w(B))).to eq(%w(A A A C A B))
22
+ expect(%w(A A B A C A B).difference(%w(C))).to eq(%w(A A B A A B))
23
+ end
8
24
  end
@@ -519,61 +519,6 @@ 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 types/)
574
- end
575
- end
576
-
577
522
  describe 'select' do
578
523
  it 'should be able to select by column names' do
579
524
  aoh = [
@@ -669,6 +614,7 @@ EOS
669
614
  end
670
615
 
671
616
  describe 'join' do
617
+ # These tests are taken from https://www.tutorialspoint.com/postgresql/postgresql_using_joins.htm
672
618
  before :all do
673
619
  @tab_a = Table.new([
674
620
  { id: 1, name: 'Paul', age: 32, address: 'California', salary: 20000, join_date: '2001-07-13' },
@@ -769,6 +715,93 @@ EOS
769
715
  end
770
716
  end
771
717
 
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
+
772
805
  describe 'output' do
773
806
  it 'should be able to return itself as an array of arrays' do
774
807
  aoh = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fat_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel E. Doherty