tb 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +62 -50
- data/bin/tb +22 -18
- data/lib/tb.rb +35 -19
- data/lib/tb/basic.rb +85 -86
- data/lib/tb/catreader.rb +33 -116
- data/lib/tb/cmd_cat.rb +31 -27
- data/lib/tb/cmd_consecutive.rb +45 -35
- data/lib/tb/cmd_crop.rb +86 -52
- data/lib/tb/cmd_cross.rb +113 -71
- data/lib/tb/cmd_cut.rb +49 -44
- data/lib/tb/cmd_git_log.rb +193 -0
- data/lib/tb/cmd_grep.rb +43 -32
- data/lib/tb/cmd_group.rb +63 -39
- data/lib/tb/cmd_gsub.rb +53 -43
- data/lib/tb/cmd_help.rb +51 -24
- data/lib/tb/cmd_join.rb +32 -35
- data/lib/tb/cmd_ls.rb +233 -205
- data/lib/tb/cmd_mheader.rb +47 -37
- data/lib/tb/cmd_nest.rb +94 -0
- data/lib/tb/cmd_newfield.rb +29 -33
- data/lib/tb/cmd_rename.rb +40 -32
- data/lib/tb/cmd_shape.rb +31 -24
- data/lib/tb/cmd_sort.rb +46 -25
- data/lib/tb/cmd_svn_log.rb +47 -28
- data/lib/tb/cmd_tar_tvf.rb +447 -0
- data/lib/tb/cmd_to_csv.rb +60 -0
- data/lib/tb/cmd_to_json.rb +60 -0
- data/lib/tb/cmd_to_pnm.rb +48 -0
- data/lib/tb/cmd_to_pp.rb +71 -0
- data/lib/tb/cmd_to_tsv.rb +48 -0
- data/lib/tb/cmd_to_yaml.rb +52 -0
- data/lib/tb/cmd_unnest.rb +118 -0
- data/lib/tb/cmdmain.rb +24 -20
- data/lib/tb/cmdtop.rb +33 -25
- data/lib/tb/cmdutil.rb +26 -66
- data/lib/tb/csv.rb +46 -34
- data/lib/tb/enum.rb +294 -0
- data/lib/tb/enumerable.rb +198 -7
- data/lib/tb/enumerator.rb +73 -0
- data/lib/tb/fieldset.rb +27 -19
- data/lib/tb/fileenumerator.rb +365 -0
- data/lib/tb/json.rb +50 -0
- data/lib/tb/pager.rb +6 -6
- data/lib/tb/pairs.rb +227 -0
- data/lib/tb/pnm.rb +23 -22
- data/lib/tb/reader.rb +52 -49
- data/lib/tb/record.rb +48 -19
- data/lib/tb/revcmp.rb +38 -0
- data/lib/tb/ropen.rb +74 -57
- data/lib/tb/search.rb +25 -21
- data/lib/tb/tsv.rb +31 -34
- data/sample/excel2csv +24 -20
- data/sample/poi-xls2csv.rb +24 -20
- data/sample/poi-xls2csv.sh +22 -18
- data/sample/tbplot +185 -127
- data/test-all-cov.rb +3 -3
- data/test-all.rb +1 -1
- data/test/test_basic.rb +26 -10
- data/test/test_catreader.rb +7 -6
- data/test/test_cmd_cat.rb +32 -0
- data/test/test_cmd_consecutive.rb +10 -0
- data/test/test_cmd_crop.rb +4 -4
- data/test/test_cmd_cross.rb +16 -4
- data/test/test_cmd_git_log.rb +46 -0
- data/test/test_cmd_help.rb +17 -12
- data/test/test_cmd_join.rb +21 -1
- data/test/test_cmd_ls.rb +3 -4
- data/test/test_cmd_mheader.rb +17 -11
- data/test/test_cmd_nest.rb +49 -0
- data/test/test_cmd_sort.rb +15 -0
- data/test/test_cmd_tar_tvf.rb +281 -0
- data/test/{test_cmd_csv.rb → test_cmd_to_csv.rb} +35 -21
- data/test/{test_cmd_json.rb → test_cmd_to_json.rb} +31 -3
- data/test/{test_cmd_pnm.rb → test_cmd_to_pnm.rb} +2 -2
- data/test/{test_cmd_pp.rb → test_cmd_to_pp.rb} +4 -4
- data/test/{test_cmd_tsv.rb → test_cmd_to_tsv.rb} +4 -4
- data/test/{test_cmd_yaml.rb → test_cmd_to_yaml.rb} +3 -3
- data/test/test_cmd_unnest.rb +89 -0
- data/test/test_cmdtty.rb +19 -13
- data/test/test_enumerable.rb +83 -1
- data/test/test_fileenumerator.rb +265 -0
- data/test/test_json.rb +15 -0
- data/test/test_pager.rb +3 -4
- data/test/test_pairs.rb +122 -0
- data/test/test_pnm.rb +24 -24
- data/test/test_reader.rb +35 -13
- data/test/test_revcmp.rb +10 -0
- data/test/test_tbenum.rb +173 -0
- metadata +51 -23
- data/lib/tb/cmd_csv.rb +0 -42
- data/lib/tb/cmd_json.rb +0 -60
- data/lib/tb/cmd_pnm.rb +0 -43
- data/lib/tb/cmd_pp.rb +0 -70
- data/lib/tb/cmd_tsv.rb +0 -43
- data/lib/tb/cmd_yaml.rb +0 -47
data/README
CHANGED
@@ -128,48 +128,56 @@ There are more subcommands.
|
|
128
128
|
% tb help
|
129
129
|
Usage:
|
130
130
|
tb help [OPTS] [SUBCOMMAND]
|
131
|
-
tb csv [OPTS] [TABLE]
|
132
|
-
tb tsv [OPTS] [TABLE]
|
133
|
-
tb
|
134
|
-
tb
|
135
|
-
tb
|
136
|
-
tb
|
137
|
-
tb
|
131
|
+
tb to-csv [OPTS] [TABLE ...]
|
132
|
+
tb to-tsv [OPTS] [TABLE]
|
133
|
+
tb to-pnm [OPTS] [TABLE]
|
134
|
+
tb to-json [OPTS] [TABLE]
|
135
|
+
tb to-yaml [OPTS] [TABLE]
|
136
|
+
tb to-pp [OPTS] [TABLE]
|
137
|
+
tb grep [OPTS] REGEXP [TABLE ...]
|
138
|
+
tb gsub [OPTS] REGEXP STRING [TABLE ...]
|
138
139
|
tb sort [OPTS] [TABLE]
|
139
140
|
tb cut [OPTS] FIELD,... [TABLE]
|
140
141
|
tb rename [OPTS] SRC,DST,... [TABLE]
|
141
142
|
tb newfield [OPTS] FIELD RUBY-EXP [TABLE]
|
142
143
|
tb cat [OPTS] [TABLE ...]
|
143
|
-
tb join [OPTS] [
|
144
|
-
tb
|
145
|
-
tb
|
144
|
+
tb join [OPTS] [TABLE1 TABLE2 ...]
|
145
|
+
tb consecutive [OPTS] [TABLE ...]
|
146
|
+
tb group [OPTS] KEY-FIELD1,... [TABLE ...]
|
147
|
+
tb cross [OPTS] HKEY-FIELD1,... VKEY-FIELD1,... [TABLE ...]
|
146
148
|
tb shape [OPTS] [TABLE ...]
|
147
149
|
tb mheader [OPTS] [TABLE]
|
148
|
-
tb crop [OPTS] [TABLE]
|
150
|
+
tb crop [OPTS] [TABLE ...]
|
151
|
+
tb ls [OPTS] [FILE ...]
|
152
|
+
tb svn-log [OPTS] -- [SVN-LOG-ARGS]
|
149
153
|
|
150
154
|
== Command Line Tool
|
151
155
|
|
152
156
|
tb command has many subcommands.
|
153
157
|
|
154
|
-
help
|
155
|
-
csv :
|
156
|
-
tsv :
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
158
|
+
help : Show help message of tb command.
|
159
|
+
to-csv : Convert a table to CSV (Comma Separated Value).
|
160
|
+
to-tsv : Convert a table to TSV (Tab Separated Value).
|
161
|
+
to-pnm : Convert a table to PNM (Portable Anymap: PPM, PGM, PBM).
|
162
|
+
to-json : Convert a table to JSON (JavaScript Object Notation).
|
163
|
+
to-yaml : Convert a table to YAML (YAML Ain't a Markup Language).
|
164
|
+
to-pp : Convert a table to pretty printed format.
|
165
|
+
grep : Search rows using regexp or ruby expression.
|
166
|
+
gsub : Substitute cells.
|
167
|
+
sort : Sort rows.
|
168
|
+
cut : Select columns.
|
169
|
+
rename : Rename field names.
|
170
|
+
newfield : Add a field.
|
171
|
+
cat : Concatenate tables vertically.
|
172
|
+
join : Concatenate tables horizontally as left/right/full natural join.
|
173
|
+
consecutive : Concatenate consecutive rows.
|
174
|
+
group : Group and aggregate rows.
|
175
|
+
cross : Create a contingency table.
|
176
|
+
shape : Show table size.
|
177
|
+
mheader : Collapse multi rows header.
|
178
|
+
crop : Extract rectangle in a table.
|
179
|
+
ls : List directory entries as a table.
|
180
|
+
svn-log : Show the SVN log as a table.
|
173
181
|
|
174
182
|
== Install
|
175
183
|
|
@@ -187,25 +195,29 @@ Tanaka Akira <akr@fsij.org>
|
|
187
195
|
== License
|
188
196
|
|
189
197
|
Redistribution and use in source and binary forms, with or without
|
190
|
-
modification, are permitted provided that the following conditions
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
OF
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
OF
|
198
|
+
modification, are permitted provided that the following conditions
|
199
|
+
are met:
|
200
|
+
|
201
|
+
1. Redistributions of source code must retain the above copyright
|
202
|
+
notice, this list of conditions and the following disclaimer.
|
203
|
+
2. Redistributions in binary form must reproduce the above
|
204
|
+
copyright notice, this list of conditions and the following
|
205
|
+
disclaimer in the documentation and/or other materials provided
|
206
|
+
with the distribution.
|
207
|
+
3. The name of the author may not be used to endorse or promote
|
208
|
+
products derived from this software without specific prior
|
209
|
+
written permission.
|
210
|
+
|
211
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
212
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
213
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
214
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
215
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
216
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
217
|
+
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
218
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
219
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
220
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
221
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
210
222
|
|
211
223
|
(The modified BSD licence)
|
data/bin/tb
CHANGED
@@ -3,26 +3,30 @@
|
|
3
3
|
# Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions
|
6
|
+
# modification, are permitted provided that the following conditions
|
7
|
+
# are met:
|
7
8
|
#
|
8
|
-
# 1. Redistributions of source code must retain the above copyright
|
9
|
-
# list of conditions and the following disclaimer.
|
10
|
-
# 2. Redistributions in binary form must reproduce the above
|
11
|
-
# this list of conditions and the following
|
12
|
-
# and/or other materials provided
|
13
|
-
#
|
14
|
-
#
|
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.
|
15
18
|
#
|
16
|
-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
17
|
-
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
-
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
-
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# IN
|
25
|
-
# OF
|
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.
|
26
30
|
|
27
31
|
require 'tb/cmdtop'
|
28
32
|
|
data/lib/tb.rb
CHANGED
@@ -1,37 +1,53 @@
|
|
1
1
|
# lib/tb.rb - entry file for table library
|
2
2
|
#
|
3
|
-
# Copyright (C) 2010-
|
3
|
+
# Copyright (C) 2010-2012 Tanaka Akira <akr@fsij.org>
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions
|
6
|
+
# modification, are permitted provided that the following conditions
|
7
|
+
# are met:
|
7
8
|
#
|
8
|
-
# 1. Redistributions of source code must retain the above copyright
|
9
|
-
# list of conditions and the following disclaimer.
|
10
|
-
# 2. Redistributions in binary form must reproduce the above
|
11
|
-
# this list of conditions and the following
|
12
|
-
# and/or other materials provided
|
13
|
-
#
|
14
|
-
#
|
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.
|
15
18
|
#
|
16
|
-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
17
|
-
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
-
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
-
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# IN
|
25
|
-
# OF
|
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.
|
26
30
|
|
31
|
+
require 'tempfile'
|
32
|
+
|
33
|
+
class Tb
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'pp'
|
37
|
+
require 'tb/enum'
|
38
|
+
require 'tb/enumerator'
|
39
|
+
require 'tb/pairs'
|
27
40
|
require 'tb/basic'
|
28
41
|
require 'tb/record'
|
29
42
|
require 'tb/csv'
|
30
43
|
require 'tb/tsv'
|
31
44
|
require 'tb/pnm'
|
45
|
+
require 'tb/json'
|
32
46
|
require 'tb/reader'
|
33
47
|
require 'tb/ropen'
|
34
48
|
require 'tb/catreader'
|
35
49
|
require 'tb/fieldset'
|
36
50
|
require 'tb/search'
|
37
51
|
require 'tb/enumerable'
|
52
|
+
require 'tb/fileenumerator'
|
53
|
+
require 'tb/revcmp'
|
data/lib/tb/basic.rb
CHANGED
@@ -1,30 +1,32 @@
|
|
1
1
|
# lib/tb/basic.rb - basic fetures for table library
|
2
2
|
#
|
3
|
-
# Copyright (C) 2010-
|
3
|
+
# Copyright (C) 2010-2012 Tanaka Akira <akr@fsij.org>
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions
|
6
|
+
# modification, are permitted provided that the following conditions
|
7
|
+
# are met:
|
7
8
|
#
|
8
|
-
# 1. Redistributions of source code must retain the above copyright
|
9
|
-
# list of conditions and the following disclaimer.
|
10
|
-
# 2. Redistributions in binary form must reproduce the above
|
11
|
-
# this list of conditions and the following
|
12
|
-
# and/or other materials provided
|
13
|
-
#
|
14
|
-
#
|
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.
|
15
18
|
#
|
16
|
-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
17
|
-
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
-
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
-
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# IN
|
25
|
-
# OF
|
26
|
-
|
27
|
-
require 'pp'
|
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.
|
28
30
|
|
29
31
|
# Tb represents a set of records.
|
30
32
|
# A record contains field values accessed by field names.
|
@@ -53,7 +55,7 @@ require 'pp'
|
|
53
55
|
# It is an error to access a record by recordid which is not allocated.
|
54
56
|
#
|
55
57
|
class Tb
|
56
|
-
include
|
58
|
+
include Tb::Enum
|
57
59
|
|
58
60
|
# :call-seq:
|
59
61
|
# Tb.new
|
@@ -142,7 +144,7 @@ class Tb
|
|
142
144
|
|
143
145
|
def check_recordid(recordid)
|
144
146
|
recordid = check_recordid_type(recordid)
|
145
|
-
if !@recordid2index.
|
147
|
+
if !@recordid2index.has_key?(recordid)
|
146
148
|
raise IndexError, "unexpected recordid: #{recordid.inspect}"
|
147
149
|
end
|
148
150
|
recordid
|
@@ -159,7 +161,7 @@ class Tb
|
|
159
161
|
|
160
162
|
def check_field(field)
|
161
163
|
field = check_field_type(field)
|
162
|
-
unless @tbl.
|
164
|
+
unless @tbl.has_key? field
|
163
165
|
raise ArgumentError, "field not defined: #{field.inspect}"
|
164
166
|
end
|
165
167
|
field
|
@@ -198,7 +200,7 @@ class Tb
|
|
198
200
|
if field.start_with?("_")
|
199
201
|
raise ArgumentError, "field begins with underscore: #{field.inspect}"
|
200
202
|
end
|
201
|
-
if @tbl.
|
203
|
+
if @tbl.has_key? field
|
202
204
|
raise ArgumentError, "field already defined: #{field.inspect}"
|
203
205
|
end
|
204
206
|
@tbl[field] = []
|
@@ -347,6 +349,32 @@ class Tb
|
|
347
349
|
@recordid2index.size
|
348
350
|
end
|
349
351
|
|
352
|
+
# :call-seq:
|
353
|
+
# table.empty?
|
354
|
+
#
|
355
|
+
# returns true if there is no record.
|
356
|
+
#
|
357
|
+
# t0 = Tb.new %w[fruit]
|
358
|
+
# pp t0
|
359
|
+
# #=> #<Tb>
|
360
|
+
# p t0.empty?
|
361
|
+
# #=> true
|
362
|
+
#
|
363
|
+
# t3 = Tb.new %w[fruit],
|
364
|
+
# %w[apple],
|
365
|
+
# %w[banana],
|
366
|
+
# %w[orange]
|
367
|
+
# pp t3
|
368
|
+
# #=> #<Tb
|
369
|
+
# # {"_recordid"=>0, "fruit"=>"apple"}
|
370
|
+
# # {"_recordid"=>1, "fruit"=>"banana"}
|
371
|
+
# # {"_recordid"=>2, "fruit"=>"orange"}>
|
372
|
+
# p t3.empty?
|
373
|
+
# #=> false
|
374
|
+
def empty?
|
375
|
+
self.size == 0
|
376
|
+
end
|
377
|
+
|
350
378
|
# :call-seq:
|
351
379
|
# table.allocate_recordid -> fresh_recordid
|
352
380
|
# table.allocate_recordid(recordid) -> recordid
|
@@ -398,7 +426,7 @@ class Tb
|
|
398
426
|
@next_recordid += 1
|
399
427
|
else
|
400
428
|
recordid = check_recordid_type(recordid)
|
401
|
-
if @recordid2index.
|
429
|
+
if @recordid2index.has_key? recordid
|
402
430
|
raise ArgumentError, "recordid already used: #{recordid.inspect}"
|
403
431
|
end
|
404
432
|
@next_recordid = recordid + 1 if @next_recordid <= recordid
|
@@ -886,6 +914,17 @@ class Tb
|
|
886
914
|
}
|
887
915
|
end
|
888
916
|
|
917
|
+
# :call-seq:
|
918
|
+
# table.header_and_each(header_proc) {|record| ... }
|
919
|
+
#
|
920
|
+
# +header_and_each+ calls _header_proc_ at first.
|
921
|
+
# The block is called for each record after that.
|
922
|
+
#
|
923
|
+
def header_and_each(header_proc, &block)
|
924
|
+
header_proc.call(list_fields) if header_proc
|
925
|
+
self.each(&block)
|
926
|
+
end
|
927
|
+
|
889
928
|
# :call-seq:
|
890
929
|
# table.filter {|record| ... }
|
891
930
|
def filter
|
@@ -898,73 +937,33 @@ class Tb
|
|
898
937
|
t
|
899
938
|
end
|
900
939
|
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
total_fields = fields1 | fields2
|
909
|
-
unique_fields2 = fields2 - common_fields
|
910
|
-
h = {}
|
911
|
-
table2.each {|rec2|
|
912
|
-
k = rec2.values_at(*common_fields)
|
913
|
-
(h[k] ||= []) << rec2
|
940
|
+
def natjoin2(table2, missing=nil, retain_left=false, retain_right=false)
|
941
|
+
t1 = Tb::Enumerator.new {|y|
|
942
|
+
self.with_header {|h0|
|
943
|
+
y.set_header h0
|
944
|
+
}.each {|record|
|
945
|
+
y.yield record.to_h
|
946
|
+
}
|
914
947
|
}
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
values = rec1.values_at(*fields1)
|
921
|
-
rec2_list.each {|rec2|
|
922
|
-
result.insert_values total_fields, values + rec2.values_at(*unique_fields2)
|
948
|
+
t2 = Tb::Enumerator.new {|y|
|
949
|
+
table2.with_header {|h0|
|
950
|
+
y.set_header h0
|
951
|
+
}.each {|record|
|
952
|
+
y.yield record.to_h
|
923
953
|
}
|
924
954
|
}
|
955
|
+
er = t1.natjoin2(t2, missing, retain_left, retain_right)
|
956
|
+
result = nil
|
957
|
+
er.with_header {|header|
|
958
|
+
result = Tb.new header
|
959
|
+
}.each {|pairs|
|
960
|
+
result.insert pairs
|
961
|
+
}
|
925
962
|
result
|
926
963
|
end
|
927
964
|
|
928
|
-
# :call-seq:
|
929
|
-
# table1.natjoin2_outer(table2, missing=nil, retain_left=true, retain_right=true)
|
930
965
|
def natjoin2_outer(table2, missing=nil, retain_left=true, retain_right=true)
|
931
|
-
|
932
|
-
fields1 = table1.list_fields
|
933
|
-
fields2 = table2.list_fields
|
934
|
-
common_fields = fields1 & fields2
|
935
|
-
total_fields = fields1 | fields2
|
936
|
-
unique_fields2 = fields2 - common_fields
|
937
|
-
fields2_extended = total_fields.map {|f| fields2.include?(f) ? f : nil }
|
938
|
-
h = {}
|
939
|
-
table2.each {|rec2|
|
940
|
-
k = rec2.values_at(*common_fields)
|
941
|
-
(h[k] ||= []) << rec2
|
942
|
-
}
|
943
|
-
result = Tb.new(total_fields)
|
944
|
-
ids2 = {}
|
945
|
-
table1.each {|rec1|
|
946
|
-
k = rec1.values_at(*common_fields)
|
947
|
-
rec2_list = h[k]
|
948
|
-
values = rec1.values_at(*fields1)
|
949
|
-
if !rec2_list || rec2_list.empty?
|
950
|
-
if retain_left
|
951
|
-
result.insert_values total_fields, values + unique_fields2.map { missing }
|
952
|
-
end
|
953
|
-
else
|
954
|
-
rec2_list.each {|rec2|
|
955
|
-
ids2[rec2['_recordid']] = true
|
956
|
-
result.insert_values total_fields, values + rec2.values_at(*unique_fields2)
|
957
|
-
}
|
958
|
-
end
|
959
|
-
}
|
960
|
-
if retain_right
|
961
|
-
table2.each {|rec2|
|
962
|
-
if !ids2[rec2['_recordid']]
|
963
|
-
result.insert_values total_fields, fields2_extended.map {|f| f ? rec2[f] : missing }
|
964
|
-
end
|
965
|
-
}
|
966
|
-
end
|
967
|
-
result
|
966
|
+
natjoin2(table2, missing, retain_left, retain_right)
|
968
967
|
end
|
969
968
|
|
970
969
|
# :call-seq:
|