tb 0.9 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README +13 -11
- data/lib/tb.rb +14 -6
- data/lib/tb/catreader.rb +2 -2
- data/lib/tb/cmd_consecutive.rb +6 -2
- data/lib/tb/cmd_crop.rb +22 -3
- data/lib/tb/cmd_cross.rb +24 -0
- data/lib/tb/cmd_cut.rb +20 -10
- data/lib/tb/cmd_git.rb +20 -7
- data/lib/tb/cmd_group.rb +32 -0
- data/lib/tb/cmd_gsub.rb +21 -0
- data/lib/tb/cmd_join.rb +28 -0
- data/lib/tb/cmd_ls.rb +9 -0
- data/lib/tb/cmd_melt.rb +15 -0
- data/lib/tb/cmd_mheader.rb +15 -0
- data/lib/tb/cmd_nest.rb +27 -6
- data/lib/tb/cmd_newfield.rb +19 -2
- data/lib/tb/cmd_rename.rb +20 -0
- data/lib/tb/{cmd_grep.rb → cmd_search.rb} +37 -23
- data/lib/tb/cmd_shape.rb +69 -25
- data/lib/tb/cmd_sort.rb +20 -0
- data/lib/tb/cmd_tar.rb +38 -0
- data/lib/tb/cmd_to_json.rb +2 -2
- data/lib/tb/cmd_to_ltsv.rb +3 -3
- data/lib/tb/cmd_to_pnm.rb +3 -3
- data/lib/tb/cmd_to_tsv.rb +3 -3
- data/lib/tb/cmd_to_yaml.rb +3 -3
- data/lib/tb/cmd_unmelt.rb +15 -0
- data/lib/tb/cmd_unnest.rb +31 -7
- data/lib/tb/cmdmain.rb +2 -0
- data/lib/tb/cmdtop.rb +1 -1
- data/lib/tb/cmdutil.rb +9 -62
- data/lib/tb/csv.rb +21 -79
- data/lib/tb/enumerable.rb +42 -68
- data/lib/tb/enumerator.rb +15 -7
- data/lib/tb/{fieldset.rb → hashreader.rb} +37 -56
- data/lib/tb/hashwriter.rb +54 -0
- data/lib/tb/headerreader.rb +108 -0
- data/lib/tb/headerwriter.rb +116 -0
- data/lib/tb/json.rb +17 -15
- data/lib/tb/ltsv.rb +35 -96
- data/lib/tb/ndjson.rb +63 -0
- data/lib/tb/numericreader.rb +66 -0
- data/lib/tb/numericwriter.rb +61 -0
- data/lib/tb/pnm.rb +206 -200
- data/lib/tb/ropen.rb +54 -59
- data/lib/tb/tsv.rb +39 -71
- data/sample/excel2csv +24 -25
- data/sample/poi-xls2csv.rb +13 -14
- data/tb.gemspec +154 -0
- data/test/test_cmd_cat.rb +28 -6
- data/test/test_cmd_consecutive.rb +8 -3
- data/test/test_cmd_cut.rb +14 -4
- data/test/test_cmd_git_log.rb +50 -50
- data/test/test_cmd_grep.rb +6 -6
- data/test/test_cmd_gsub.rb +7 -2
- data/test/test_cmd_ls.rb +70 -62
- data/test/test_cmd_shape.rb +43 -6
- data/test/test_cmd_svn_log.rb +26 -27
- data/test/test_cmd_to_csv.rb +10 -5
- data/test/test_cmd_to_json.rb +16 -0
- data/test/test_cmd_to_ltsv.rb +2 -2
- data/test/test_cmd_to_pp.rb +7 -2
- data/test/test_csv.rb +74 -62
- data/test/test_ex_enumerable.rb +0 -1
- data/test/test_fileenumerator.rb +3 -3
- data/test/test_headercsv.rb +43 -0
- data/test/test_json.rb +2 -2
- data/test/test_ltsv.rb +22 -17
- data/test/test_ndjson.rb +62 -0
- data/test/test_numericcsv.rb +36 -0
- data/test/test_pnm.rb +69 -70
- data/test/test_reader.rb +27 -124
- data/test/test_tbenum.rb +18 -18
- data/test/test_tsv.rb +21 -32
- data/test/util_tbtest.rb +12 -0
- metadata +41 -19
- data/lib/tb/basic.rb +0 -1070
- data/lib/tb/reader.rb +0 -106
- data/lib/tb/record.rb +0 -158
- data/test/test_basic.rb +0 -403
- data/test/test_fieldset.rb +0 -42
- data/test/test_record.rb +0 -61
data/lib/tb/reader.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
# lib/tb/reader.rb - Tb::Reader class
|
2
|
-
#
|
3
|
-
# Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
|
4
|
-
#
|
5
|
-
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions
|
7
|
-
# are met:
|
8
|
-
#
|
9
|
-
# 1. Redistributions of source code must retain the above copyright
|
10
|
-
# notice, this list of conditions and the following disclaimer.
|
11
|
-
# 2. Redistributions in binary form must reproduce the above
|
12
|
-
# copyright notice, this list of conditions and the following
|
13
|
-
# disclaimer in the documentation and/or other materials provided
|
14
|
-
# with the distribution.
|
15
|
-
# 3. The name of the author may not be used to endorse or promote
|
16
|
-
# products derived from this software without specific prior
|
17
|
-
# written permission.
|
18
|
-
#
|
19
|
-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
20
|
-
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
-
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
23
|
-
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
25
|
-
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
27
|
-
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
28
|
-
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
29
|
-
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
-
|
31
|
-
class Tb::Reader
|
32
|
-
include Tb::Enumerable
|
33
|
-
|
34
|
-
def initialize(opts={}, &rawreader_open)
|
35
|
-
@opt_n = opts[:numeric]
|
36
|
-
@reader_open = rawreader_open
|
37
|
-
@fieldset = nil
|
38
|
-
end
|
39
|
-
|
40
|
-
def internal_header(rawreader)
|
41
|
-
return @fieldset.header if @fieldset
|
42
|
-
if @opt_n
|
43
|
-
@fieldset = Tb::FieldSet.new
|
44
|
-
else
|
45
|
-
while ary = rawreader.shift
|
46
|
-
if ary.all? {|elt| elt.nil? || elt == '' }
|
47
|
-
next
|
48
|
-
else
|
49
|
-
@fieldset = Tb::FieldSet.new(*ary)
|
50
|
-
return @fieldset.header
|
51
|
-
end
|
52
|
-
end
|
53
|
-
@fieldset = Tb::FieldSet.new
|
54
|
-
end
|
55
|
-
return @fieldset.header
|
56
|
-
end
|
57
|
-
|
58
|
-
def index_from_field_ex(f)
|
59
|
-
raise TypeError if !@fieldset
|
60
|
-
@fieldset.index_from_field_ex(f)
|
61
|
-
end
|
62
|
-
|
63
|
-
def index_from_field(f)
|
64
|
-
raise TypeError if !@fieldset
|
65
|
-
@fieldset.index_from_field(f)
|
66
|
-
end
|
67
|
-
|
68
|
-
def field_from_index_ex(i)
|
69
|
-
raise TypeError if !@fieldset
|
70
|
-
raise ArgumentError, "negative index: #{i}" if i < 0
|
71
|
-
@fieldset.field_from_index_ex(i)
|
72
|
-
end
|
73
|
-
|
74
|
-
def field_from_index(i)
|
75
|
-
raise TypeError if !@fieldset
|
76
|
-
raise ArgumentError, "negative index: #{i}" if i < 0
|
77
|
-
@fieldset.field_from_index(i)
|
78
|
-
end
|
79
|
-
|
80
|
-
def internal_shift(rawreader)
|
81
|
-
raise TypeError if !@fieldset
|
82
|
-
ary = rawreader.shift
|
83
|
-
field_from_index_ex(ary.length-1) if ary && !ary.empty?
|
84
|
-
ary
|
85
|
-
end
|
86
|
-
|
87
|
-
def header_and_each(header_proc)
|
88
|
-
body = lambda {|rawreader|
|
89
|
-
h = self.internal_header(rawreader)
|
90
|
-
header_proc.call(h) if header_proc
|
91
|
-
while ary = self.internal_shift(rawreader)
|
92
|
-
pairs = {}
|
93
|
-
ary.each_with_index {|v, i|
|
94
|
-
f = field_from_index_ex(i)
|
95
|
-
pairs[f] = v
|
96
|
-
}
|
97
|
-
yield pairs
|
98
|
-
end
|
99
|
-
}
|
100
|
-
@reader_open.call(body)
|
101
|
-
end
|
102
|
-
|
103
|
-
def each(&block)
|
104
|
-
header_and_each(nil, &block)
|
105
|
-
end
|
106
|
-
end
|
data/lib/tb/record.rb
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
# lib/tb/record.rb - record class for table library
|
2
|
-
#
|
3
|
-
# Copyright (C) 2010-2012 Tanaka Akira <akr@fsij.org>
|
4
|
-
#
|
5
|
-
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions
|
7
|
-
# are met:
|
8
|
-
#
|
9
|
-
# 1. Redistributions of source code must retain the above copyright
|
10
|
-
# notice, this list of conditions and the following disclaimer.
|
11
|
-
# 2. Redistributions in binary form must reproduce the above
|
12
|
-
# copyright notice, this list of conditions and the following
|
13
|
-
# disclaimer in the documentation and/or other materials provided
|
14
|
-
# with the distribution.
|
15
|
-
# 3. The name of the author may not be used to endorse or promote
|
16
|
-
# products derived from this software without specific prior
|
17
|
-
# written permission.
|
18
|
-
#
|
19
|
-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
20
|
-
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
-
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
23
|
-
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
25
|
-
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
27
|
-
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
28
|
-
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
29
|
-
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
-
|
31
|
-
class Tb::Record
|
32
|
-
include Enumerable
|
33
|
-
|
34
|
-
def initialize(table, recordid)
|
35
|
-
@table = table
|
36
|
-
@recordid = recordid
|
37
|
-
end
|
38
|
-
attr_reader :table
|
39
|
-
|
40
|
-
def record_id
|
41
|
-
@recordid
|
42
|
-
end
|
43
|
-
|
44
|
-
def pretty_print(q) # :nodoc:
|
45
|
-
q.object_group(self) {
|
46
|
-
fs = @table.list_fields.reject {|f| self[f].nil? }
|
47
|
-
unless fs.empty?
|
48
|
-
q.text ':'
|
49
|
-
q.breakable
|
50
|
-
end
|
51
|
-
q.seplist(fs, nil, :each) {|f|
|
52
|
-
v = self[f]
|
53
|
-
q.group {
|
54
|
-
q.pp f
|
55
|
-
q.text '=>'
|
56
|
-
q.group(1) {
|
57
|
-
q.breakable ''
|
58
|
-
q.pp v
|
59
|
-
}
|
60
|
-
}
|
61
|
-
}
|
62
|
-
}
|
63
|
-
end
|
64
|
-
alias inspect pretty_print_inspect # :nodoc:
|
65
|
-
|
66
|
-
def has_field?(field)
|
67
|
-
@table.has_field?(field)
|
68
|
-
end
|
69
|
-
alias has_key? has_field?
|
70
|
-
alias include? has_field?
|
71
|
-
alias key? has_field?
|
72
|
-
alias member? has_field?
|
73
|
-
|
74
|
-
def [](field)
|
75
|
-
@table.get_cell(@recordid, field)
|
76
|
-
end
|
77
|
-
|
78
|
-
def []=(field, value)
|
79
|
-
@table.set_cell(@recordid, field, value)
|
80
|
-
end
|
81
|
-
|
82
|
-
def to_h
|
83
|
-
h = {}
|
84
|
-
@table.each_field {|f|
|
85
|
-
v = @table.get_cell(@recordid, f)
|
86
|
-
h[f] = v if !v.nil?
|
87
|
-
}
|
88
|
-
h
|
89
|
-
end
|
90
|
-
|
91
|
-
def to_h_with_reserved
|
92
|
-
h = {}
|
93
|
-
@table.each_field_with_reserved {|f|
|
94
|
-
v = @table.get_cell(@recordid, f)
|
95
|
-
h[f] = v if !v.nil?
|
96
|
-
}
|
97
|
-
h
|
98
|
-
end
|
99
|
-
|
100
|
-
def to_a
|
101
|
-
a = []
|
102
|
-
@table.each_field {|f|
|
103
|
-
v = @table.get_cell(@recordid, f)
|
104
|
-
a << [f, v] if !v.nil?
|
105
|
-
}
|
106
|
-
a
|
107
|
-
end
|
108
|
-
|
109
|
-
def to_a_with_reserved
|
110
|
-
a = []
|
111
|
-
@table.each_field_with_reserved {|f|
|
112
|
-
v = @table.get_cell(@recordid, f)
|
113
|
-
a << [f, v] if !v.nil?
|
114
|
-
}
|
115
|
-
a
|
116
|
-
end
|
117
|
-
|
118
|
-
def each
|
119
|
-
@table.each_field {|f|
|
120
|
-
v = @table.get_cell(@recordid, f)
|
121
|
-
yield [f, v] if !v.nil?
|
122
|
-
}
|
123
|
-
nil
|
124
|
-
end
|
125
|
-
|
126
|
-
def each_with_reserved
|
127
|
-
@table.each_field_with_reserved {|f|
|
128
|
-
v = @table.get_cell(@recordid, f)
|
129
|
-
yield [f, v] if !v.nil?
|
130
|
-
}
|
131
|
-
nil
|
132
|
-
end
|
133
|
-
|
134
|
-
def values_at(*fields)
|
135
|
-
fields.map {|f| self[f] }
|
136
|
-
end
|
137
|
-
|
138
|
-
def keys
|
139
|
-
a = []
|
140
|
-
@table.each_field {|f|
|
141
|
-
v = @table.get_cell(@recordid, f)
|
142
|
-
next if v.nil?
|
143
|
-
a << f
|
144
|
-
}
|
145
|
-
a
|
146
|
-
end
|
147
|
-
|
148
|
-
def values
|
149
|
-
a = []
|
150
|
-
@table.each_field {|f|
|
151
|
-
v = @table.get_cell(@recordid, f)
|
152
|
-
next if v.nil?
|
153
|
-
a << v
|
154
|
-
}
|
155
|
-
a
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
data/test/test_basic.rb
DELETED
@@ -1,403 +0,0 @@
|
|
1
|
-
require 'tb'
|
2
|
-
require 'test/unit'
|
3
|
-
|
4
|
-
class TestTbBasic < Test::Unit::TestCase
|
5
|
-
def test_initialize
|
6
|
-
t = Tb.new
|
7
|
-
assert_equal([], t.list_fields)
|
8
|
-
t = Tb.new %w[fruit color],
|
9
|
-
%w[apple red],
|
10
|
-
%w[banana yellow],
|
11
|
-
%w[orange orange]
|
12
|
-
assert_equal(%w[fruit color].sort, t.list_fields.sort)
|
13
|
-
a = t.to_a.map {|r| r.to_h_with_reserved }
|
14
|
-
assert_operator(a, :include?, {"_recordid"=>0, "fruit"=>"apple", "color"=>"red"})
|
15
|
-
assert_operator(a, :include?, {"_recordid"=>1, "fruit"=>"banana", "color"=>"yellow"})
|
16
|
-
assert_operator(a, :include?, {"_recordid"=>2, "fruit"=>"orange", "color"=>"orange"})
|
17
|
-
assert_equal(3, a.length)
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_replace
|
21
|
-
t1 = Tb.new %w[fruit color],
|
22
|
-
%w[apple red],
|
23
|
-
%w[banana yellow],
|
24
|
-
%w[orange orange]
|
25
|
-
t2 = Tb.new %w[grain color],
|
26
|
-
%w[rice white],
|
27
|
-
%w[wheat light-brown]
|
28
|
-
t1.replace t2
|
29
|
-
assert_equal([{"grain"=>"rice", "color"=>"white"},
|
30
|
-
{"grain"=>"wheat", "color"=>"light-brown"}],
|
31
|
-
t2.to_a.map {|rec| rec.to_h })
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_pretty_print
|
35
|
-
t = Tb.new %w[fruit color],
|
36
|
-
%w[apple red],
|
37
|
-
%w[banana yellow],
|
38
|
-
%w[orange orange]
|
39
|
-
s = t.pretty_inspect
|
40
|
-
assert_match(/fruit/, s)
|
41
|
-
assert_match(/color/, s)
|
42
|
-
assert_match(/apple/, s)
|
43
|
-
assert_match(/red/, s)
|
44
|
-
assert_match(/banana/, s)
|
45
|
-
assert_match(/yellow/, s)
|
46
|
-
assert_match(/orange/, s)
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_enumerable
|
50
|
-
t = Tb.new
|
51
|
-
assert_kind_of(Enumerable, t)
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_define_field
|
55
|
-
t = Tb.new %w[fruit color],
|
56
|
-
%w[apple red],
|
57
|
-
%w[banana yellow],
|
58
|
-
%w[orange orange]
|
59
|
-
t.define_field("namelen") {|record| record["fruit"].length }
|
60
|
-
t.each {|rec|
|
61
|
-
case rec['fruit']
|
62
|
-
when 'apple' then assert_equal(5, rec['namelen'])
|
63
|
-
when 'banana' then assert_equal(6, rec['namelen'])
|
64
|
-
when 'orange' then assert_equal(6, rec['namelen'])
|
65
|
-
else raise
|
66
|
-
end
|
67
|
-
}
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_define_field_error
|
71
|
-
t = Tb.new %w[fruit color],
|
72
|
-
%w[apple red],
|
73
|
-
%w[banana yellow],
|
74
|
-
%w[orange orange]
|
75
|
-
assert_raise(ArgumentError) { t.define_field("_foo") }
|
76
|
-
assert_raise(ArgumentError) { t.define_field("fruit") }
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_list_fields
|
80
|
-
t = Tb.new
|
81
|
-
assert_equal([], t.list_fields)
|
82
|
-
assert_equal([], t.list_fields)
|
83
|
-
assert_equal(["_recordid"], t.list_fields_all)
|
84
|
-
t = Tb.new %w[fruit color],
|
85
|
-
%w[apple red],
|
86
|
-
%w[banana yellow],
|
87
|
-
%w[orange orange]
|
88
|
-
assert_equal(%w[fruit color], t.list_fields)
|
89
|
-
assert_equal(%w[fruit color], t.list_fields)
|
90
|
-
assert_equal(%w[_recordid fruit color], t.list_fields_all)
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_list_recordids
|
94
|
-
t = Tb.new
|
95
|
-
assert_equal([], t.list_recordids)
|
96
|
-
recordid1 = t.allocate_recordid
|
97
|
-
assert_equal([recordid1], t.list_recordids)
|
98
|
-
recordid2 = t.allocate_recordid
|
99
|
-
assert_equal([recordid1, recordid2], t.list_recordids)
|
100
|
-
assert_equal(nil, t.delete_recordid(recordid1))
|
101
|
-
assert_equal([recordid2], t.list_recordids)
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_cell
|
105
|
-
t = Tb.new %w[f g]
|
106
|
-
recordid = t.allocate_recordid
|
107
|
-
assert_equal(nil, t.get_cell(recordid, :f))
|
108
|
-
t.set_cell(recordid, :f, 1)
|
109
|
-
assert_equal(1, t.get_cell(recordid, :f))
|
110
|
-
assert_equal(1, t.delete_cell(recordid, :f))
|
111
|
-
assert_equal(nil, t.get_cell(recordid, :f))
|
112
|
-
t.set_cell(recordid, :f, nil)
|
113
|
-
assert_equal(nil, t.get_cell(recordid, :f))
|
114
|
-
t.set_cell(recordid, :g, 2)
|
115
|
-
assert_equal(2, t.get_cell(recordid, :g))
|
116
|
-
t.set_cell(recordid, :g, nil)
|
117
|
-
assert_equal(nil, t.get_cell(recordid, :g))
|
118
|
-
t.delete_cell(recordid, :g)
|
119
|
-
assert_equal(nil, t.get_cell(recordid, :g))
|
120
|
-
t.delete_recordid(recordid)
|
121
|
-
assert_raise(IndexError) { t.get_cell(recordid, :g) }
|
122
|
-
assert_raise(IndexError) { t.get_cell(100, :g) }
|
123
|
-
assert_raise(IndexError) { t.get_cell(-1, :g) }
|
124
|
-
assert_raise(TypeError) { t.get_cell(:invalid_recordid, :g) }
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_each_field
|
128
|
-
t = Tb.new %w[a b z]
|
129
|
-
a = []
|
130
|
-
t.each_field_with_reserved {|f| a << f }
|
131
|
-
assert_equal(%w[_recordid a b z], a)
|
132
|
-
a = []
|
133
|
-
t.each_field {|f| a << f }
|
134
|
-
assert_equal(%w[a b z], a)
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_each_record
|
138
|
-
t = Tb.new %w[a], [1], [2]
|
139
|
-
records = []
|
140
|
-
t.each {|record| records << record.to_h_with_reserved }
|
141
|
-
assert_equal([{"_recordid"=>0, "a"=>1}, {"_recordid"=>1, "a"=>2}], records)
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_categorize
|
145
|
-
t = Tb.new %w[a b c], [1,2,3], [2,4,3]
|
146
|
-
assert_raise(ArgumentError) { t.tb_categorize('a') }
|
147
|
-
assert_equal({1=>[2], 2=>[4]}, t.tb_categorize('a', 'b'))
|
148
|
-
assert_equal({1=>{2=>[3]}, 2=>{4=>[3]}}, t.tb_categorize('a', 'b', 'c'))
|
149
|
-
assert_equal({1=>[[2,3]], 2=>[[4,3]]}, t.tb_categorize('a', ['b', 'c']))
|
150
|
-
assert_equal({[1,2]=>[3], [2,4]=>[3]}, t.tb_categorize(['a', 'b'], 'c'))
|
151
|
-
assert_equal({3=>[2,4]}, t.tb_categorize('c', 'b'))
|
152
|
-
assert_equal({3=>[true,true]}, t.tb_categorize('c', lambda {|e| true }))
|
153
|
-
assert_equal({3=>2}, t.tb_categorize('c', 'b') {|ks, vs| vs.length } )
|
154
|
-
assert_equal({3=>2}, t.tb_categorize('c', 'b',
|
155
|
-
:seed=>0,
|
156
|
-
:update=> lambda {|ks, s, v| s + 1 }))
|
157
|
-
assert_equal({true => [1,2]}, t.tb_categorize(lambda {|e| true }, 'a'))
|
158
|
-
h = t.tb_categorize('a', lambda {|e| e })
|
159
|
-
assert_equal(2, h.size)
|
160
|
-
assert_equal([1, 2], h.keys.sort)
|
161
|
-
assert_instance_of(Array, h[1])
|
162
|
-
assert_instance_of(Array, h[2])
|
163
|
-
assert_equal(1, h[1].length)
|
164
|
-
assert_equal(1, h[2].length)
|
165
|
-
assert_instance_of(Tb::Record, h[1][0])
|
166
|
-
assert_instance_of(Tb::Record, h[2][0])
|
167
|
-
assert_same(t, h[1][0].table)
|
168
|
-
assert_same(t, h[2][0].table)
|
169
|
-
assert_equal(0, h[1][0].record_id)
|
170
|
-
assert_equal(1, h[2][0].record_id)
|
171
|
-
assert_same(t, h[2][0].table)
|
172
|
-
|
173
|
-
assert_raise(ArgumentError) { t.tb_categorize(:_foo, lambda {|e| true }) }
|
174
|
-
assert_equal({3=>[2], 6=>[4]}, t.tb_categorize(lambda {|rec| rec['a'] * 3 }, 'b'))
|
175
|
-
assert_equal({[1,2]=>[[2,3]], [2,4]=>[[4,3]]}, t.tb_categorize(['a', 'b'], ['b', 'c']))
|
176
|
-
assert_equal({1=>2, 2=>4}, t.tb_categorize('a', 'b', :seed=>0, :op=>:+))
|
177
|
-
assert_raise(ArgumentError) { t.tb_categorize('a', 'b', :op=>:+, :update=>lambda {|ks, s, v| v }) }
|
178
|
-
i = -1
|
179
|
-
assert_equal({3=>[0, 1]}, t.tb_categorize('c', lambda {|e| i += 1 }))
|
180
|
-
end
|
181
|
-
|
182
|
-
def test_unique_categorize
|
183
|
-
t = Tb.new %w[a b c], [1,2,3], [2,4,4]
|
184
|
-
assert_equal({1=>3, 2=>4}, t.tb_unique_categorize("a", "c"))
|
185
|
-
assert_equal({1=>[3], 2=>[4]}, t.tb_unique_categorize("a", "c", :seed=>nil) {|seed, v| !seed ? [v] : (seed << v) })
|
186
|
-
assert_equal({1=>1, 2=>1}, t.tb_unique_categorize("a", "c", :seed=>nil) {|seed, v| !seed ? 1 : seed + 1 })
|
187
|
-
assert_equal({1=>{2=>3}, 2=>{4=>4}}, t.tb_unique_categorize("a", "b", "c"))
|
188
|
-
t.insert({"a"=>2, "b"=>7, "c"=>8})
|
189
|
-
assert_equal({1=>{2=>3}, 2=>{4=>4, 7=>8}}, t.tb_unique_categorize("a", "b", "c"))
|
190
|
-
end
|
191
|
-
|
192
|
-
def test_unique_categorize_ambiguous
|
193
|
-
t = Tb.new %w[a b c], [1,2,3], [1,4,4]
|
194
|
-
assert_raise(ArgumentError) { t.tb_unique_categorize("a", "c") }
|
195
|
-
assert_equal({1=>[3,4]}, t.tb_unique_categorize("a", "c", :seed=>nil) {|seed, v| !seed ? [v] : (seed << v) })
|
196
|
-
assert_equal({1=>2}, t.tb_unique_categorize("a", "c", :seed=>nil) {|seed, v| !seed ? 1 : seed + 1 })
|
197
|
-
end
|
198
|
-
|
199
|
-
def test_category_count
|
200
|
-
t = Tb.new %w[a b c], [1,2,3], [2,4,3]
|
201
|
-
assert_equal({1=>1, 2=>1}, t.tb_category_count("a"))
|
202
|
-
assert_equal({2=>1, 4=>1}, t.tb_category_count("b"))
|
203
|
-
assert_equal({3=>2}, t.tb_category_count("c"))
|
204
|
-
assert_equal({3=>{1=>1, 2=>1}}, t.tb_category_count("c", "a"))
|
205
|
-
end
|
206
|
-
|
207
|
-
def test_natjoin2
|
208
|
-
t1 = Tb.new %w[a b], %w[1 2], %w[3 4], %w[0 4]
|
209
|
-
t2 = Tb.new %w[b c], %w[2 3], %w[4 5], %w[5 8]
|
210
|
-
t3 = t1.natjoin2(t2)
|
211
|
-
assert_equal([{"a"=>"1", "b"=>"2", "c"=>"3"},
|
212
|
-
{"a"=>"3", "b"=>"4", "c"=>"5"},
|
213
|
-
{"a"=>"0", "b"=>"4", "c"=>"5"}],
|
214
|
-
t3.to_a.map {|r| r.to_h })
|
215
|
-
end
|
216
|
-
|
217
|
-
def test_natjoin2_nocommon
|
218
|
-
t1 = Tb.new %w[a b], %w[1 2], %w[3 4]
|
219
|
-
t2 = Tb.new %w[c d], %w[5 6], %w[7 8]
|
220
|
-
t3 = t1.natjoin2(t2)
|
221
|
-
assert_equal([{"a"=>"1", "b"=>"2", "c"=>"5", "d"=>"6"},
|
222
|
-
{"a"=>"1", "b"=>"2", "c"=>"7", "d"=>"8"},
|
223
|
-
{"a"=>"3", "b"=>"4", "c"=>"5", "d"=>"6"},
|
224
|
-
{"a"=>"3", "b"=>"4", "c"=>"7", "d"=>"8"}],
|
225
|
-
t3.to_a.map {|r| r.to_h })
|
226
|
-
end
|
227
|
-
|
228
|
-
def test_natjoin2_outer
|
229
|
-
t1 = Tb.new %w[a b], %w[1 2], %w[3 4], %w[0 4], %w[0 1]
|
230
|
-
t2 = Tb.new %w[b c], %w[2 3], %w[4 5], %w[5 8]
|
231
|
-
t3 = t1.natjoin2_outer(t2)
|
232
|
-
assert_equal([{"a"=>"0", "b"=>"1"},
|
233
|
-
{"a"=>"1", "b"=>"2", "c"=>"3"},
|
234
|
-
{"a"=>"3", "b"=>"4", "c"=>"5"},
|
235
|
-
{"a"=>"0", "b"=>"4", "c"=>"5"},
|
236
|
-
{"b"=>"5", "c"=>"8"}],
|
237
|
-
t3.to_a.map {|r| r.to_h })
|
238
|
-
end
|
239
|
-
|
240
|
-
def test_fmap!
|
241
|
-
t = Tb.new %w[a b], %w[1 2], %w[3 4]
|
242
|
-
t.fmap!("a") {|record, v| "foo" + v }
|
243
|
-
assert_equal([{"_recordid"=>0, "a"=>"foo1", "b"=>"2"},
|
244
|
-
{"_recordid"=>1, "a"=>"foo3", "b"=>"4"}], t.to_a.map {|r| r.to_h_with_reserved })
|
245
|
-
end
|
246
|
-
|
247
|
-
def test_delete_field
|
248
|
-
t = Tb.new(%w[a b], %w[1 2], %w[3 4])
|
249
|
-
t.delete_field("a")
|
250
|
-
assert_equal([{"_recordid"=>0, "b"=>"2"},
|
251
|
-
{"_recordid"=>1, "b"=>"4"}], t.to_a.map {|r| r.to_h_with_reserved })
|
252
|
-
end
|
253
|
-
|
254
|
-
def test_delete_recordid
|
255
|
-
t = Tb.new %w[a]
|
256
|
-
recordid = t.insert({"a"=>"foo"})
|
257
|
-
t.insert({"a"=>"bar"})
|
258
|
-
t.delete_recordid(recordid)
|
259
|
-
t.insert({"a"=>"foo"})
|
260
|
-
records = []
|
261
|
-
t.each {|record|
|
262
|
-
record = record.to_h
|
263
|
-
record.delete('_recordid')
|
264
|
-
records << record
|
265
|
-
}
|
266
|
-
records = records.sort_by {|record| record['a'] }
|
267
|
-
assert_equal([{"a"=>"bar"}, {"a"=>"foo"}], records)
|
268
|
-
end
|
269
|
-
|
270
|
-
def test_rename_field
|
271
|
-
t1 = Tb.new %w[a b], [1, 2]
|
272
|
-
assert_equal([{"_recordid"=>0, "a"=>1, "b"=>2}], t1.to_a.map {|r| r.to_h_with_reserved })
|
273
|
-
t2 = t1.rename_field("a" => "c", "b" => "d")
|
274
|
-
assert_equal([{"_recordid"=>0, "a"=>1, "b"=>2}], t1.to_a.map {|r| r.to_h_with_reserved })
|
275
|
-
assert_equal([{"_recordid"=>0, "c"=>1, "d"=>2}], t2.to_a.map {|r| r.to_h_with_reserved })
|
276
|
-
end
|
277
|
-
|
278
|
-
def test_allocate_recordid
|
279
|
-
t = Tb.new
|
280
|
-
recordid1 = t.allocate_recordid(100)
|
281
|
-
assert_equal(100, recordid1)
|
282
|
-
recordid2 = t.allocate_recordid(200)
|
283
|
-
assert_equal(200, recordid2)
|
284
|
-
recordid3 = t.allocate_recordid
|
285
|
-
assert(recordid3 != recordid1)
|
286
|
-
assert(recordid3 != recordid2)
|
287
|
-
end
|
288
|
-
|
289
|
-
def test_allocate_recordid_error
|
290
|
-
t = Tb.new
|
291
|
-
recordid1 = t.allocate_recordid
|
292
|
-
assert_raise(ArgumentError) { t.allocate_recordid(recordid1) }
|
293
|
-
end
|
294
|
-
|
295
|
-
def test_allocate_record
|
296
|
-
t = Tb.new
|
297
|
-
rec1 = t.allocate_record
|
298
|
-
assert_kind_of(Tb::Record, rec1)
|
299
|
-
rec2 = t.allocate_record(200)
|
300
|
-
assert_kind_of(Tb::Record, rec2)
|
301
|
-
assert_equal(200, rec2.record_id)
|
302
|
-
end
|
303
|
-
|
304
|
-
def test_reorder_fields!
|
305
|
-
t = Tb.new %w[fruit color],
|
306
|
-
%w[apple red],
|
307
|
-
%w[banana yellow],
|
308
|
-
%w[orange orange]
|
309
|
-
assert_equal(%w[fruit color], t.list_fields)
|
310
|
-
t.reorder_fields! %w[color fruit]
|
311
|
-
assert_equal(%w[_recordid color fruit], t.list_fields_all)
|
312
|
-
t.reorder_fields! %w[fruit _recordid color]
|
313
|
-
assert_equal(%w[fruit _recordid color], t.list_fields_all)
|
314
|
-
end
|
315
|
-
|
316
|
-
def test_has_field?
|
317
|
-
t = Tb.new %w[fruit color],
|
318
|
-
%w[apple red],
|
319
|
-
%w[banana yellow],
|
320
|
-
%w[orange orange]
|
321
|
-
assert_equal(true, t.has_field?("fruit"))
|
322
|
-
assert_equal(false, t.has_field?("foo"))
|
323
|
-
end
|
324
|
-
|
325
|
-
def test_filter
|
326
|
-
t = Tb.new %w[fruit color],
|
327
|
-
%w[apple red],
|
328
|
-
%w[banana yellow],
|
329
|
-
%w[orange orange]
|
330
|
-
t2 = t.filter {|rec| rec["fruit"] == "banana" }
|
331
|
-
assert_equal(1, t2.size)
|
332
|
-
end
|
333
|
-
|
334
|
-
def test_reorder_records_by
|
335
|
-
t = Tb.new %w[fruit color],
|
336
|
-
%w[apple red],
|
337
|
-
%w[banana yellow],
|
338
|
-
%w[orange orange]
|
339
|
-
t2 = t.reorder_records_by {|rec| rec["color"] }
|
340
|
-
assert_equal(t.map {|rec| rec["color"] }.sort, t2.map {|rec| rec["color"] })
|
341
|
-
end
|
342
|
-
|
343
|
-
def test_insert_values
|
344
|
-
t = Tb.new %w[fruit color],
|
345
|
-
%w[apple red],
|
346
|
-
%w[banana yellow],
|
347
|
-
%w[orange orange]
|
348
|
-
res = t.insert_values(["fruit", "color"], ["grape", "purple"], ["cherry", "red"])
|
349
|
-
assert_equal([3, 4], res)
|
350
|
-
assert_equal(["grape", "purple"], t.get_values(3, "fruit", "color"))
|
351
|
-
assert_equal(["cherry", "red"], t.get_values(4, "fruit", "color"))
|
352
|
-
end
|
353
|
-
|
354
|
-
def test_insert_values_error
|
355
|
-
t = Tb.new %w[fruit color],
|
356
|
-
%w[apple red],
|
357
|
-
%w[banana yellow],
|
358
|
-
%w[orange orange]
|
359
|
-
assert_raise(ArgumentError) { t.insert_values(["fruit", "color"], ["grape", "purple", "red"]) }
|
360
|
-
end
|
361
|
-
|
362
|
-
def test_concat
|
363
|
-
t1 = Tb.new %w[fruit color],
|
364
|
-
%w[apple red]
|
365
|
-
t2 = Tb.new %w[fruit color],
|
366
|
-
%w[banana yellow],
|
367
|
-
%w[orange orange]
|
368
|
-
t3 = t1.concat(t2)
|
369
|
-
assert_same(t1, t3)
|
370
|
-
assert_equal(3, t1.size)
|
371
|
-
assert_equal(["banana", "yellow"], t1.get_values(1, "fruit", "color"))
|
372
|
-
assert_equal(["orange", "orange"], t1.get_values(2, "fruit", "color"))
|
373
|
-
end
|
374
|
-
|
375
|
-
def test_each_record_values
|
376
|
-
t = Tb.new %w[fruit color],
|
377
|
-
%w[banana yellow],
|
378
|
-
%w[orange orange]
|
379
|
-
rs = []
|
380
|
-
t.each_record_values('fruit') {|r| rs << r }
|
381
|
-
assert_equal([['banana'], ['orange']], rs)
|
382
|
-
rs = []
|
383
|
-
t.each_record_values('fruit', 'color') {|r| rs << r }
|
384
|
-
assert_equal([['banana', 'yellow'], ['orange', 'orange']], rs)
|
385
|
-
end
|
386
|
-
|
387
|
-
def test_with_header
|
388
|
-
t = Tb.new %w[a b], [1, 2], [3, 4]
|
389
|
-
result = []
|
390
|
-
t.with_header {|x|
|
391
|
-
result << x
|
392
|
-
}.each {|x|
|
393
|
-
result << x
|
394
|
-
}
|
395
|
-
assert_equal(3, result.length)
|
396
|
-
assert_equal(%w[a b], result[0])
|
397
|
-
assert_kind_of(Tb::Record, result[1])
|
398
|
-
assert_kind_of(Tb::Record, result[2])
|
399
|
-
assert_equal([["a", 1], ["b", 2]], result[1].to_a)
|
400
|
-
assert_equal([["a", 3], ["b", 4]], result[2].to_a)
|
401
|
-
end
|
402
|
-
|
403
|
-
end
|