tb 0.2 → 0.3

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.
Files changed (95) hide show
  1. data/README +62 -50
  2. data/bin/tb +22 -18
  3. data/lib/tb.rb +35 -19
  4. data/lib/tb/basic.rb +85 -86
  5. data/lib/tb/catreader.rb +33 -116
  6. data/lib/tb/cmd_cat.rb +31 -27
  7. data/lib/tb/cmd_consecutive.rb +45 -35
  8. data/lib/tb/cmd_crop.rb +86 -52
  9. data/lib/tb/cmd_cross.rb +113 -71
  10. data/lib/tb/cmd_cut.rb +49 -44
  11. data/lib/tb/cmd_git_log.rb +193 -0
  12. data/lib/tb/cmd_grep.rb +43 -32
  13. data/lib/tb/cmd_group.rb +63 -39
  14. data/lib/tb/cmd_gsub.rb +53 -43
  15. data/lib/tb/cmd_help.rb +51 -24
  16. data/lib/tb/cmd_join.rb +32 -35
  17. data/lib/tb/cmd_ls.rb +233 -205
  18. data/lib/tb/cmd_mheader.rb +47 -37
  19. data/lib/tb/cmd_nest.rb +94 -0
  20. data/lib/tb/cmd_newfield.rb +29 -33
  21. data/lib/tb/cmd_rename.rb +40 -32
  22. data/lib/tb/cmd_shape.rb +31 -24
  23. data/lib/tb/cmd_sort.rb +46 -25
  24. data/lib/tb/cmd_svn_log.rb +47 -28
  25. data/lib/tb/cmd_tar_tvf.rb +447 -0
  26. data/lib/tb/cmd_to_csv.rb +60 -0
  27. data/lib/tb/cmd_to_json.rb +60 -0
  28. data/lib/tb/cmd_to_pnm.rb +48 -0
  29. data/lib/tb/cmd_to_pp.rb +71 -0
  30. data/lib/tb/cmd_to_tsv.rb +48 -0
  31. data/lib/tb/cmd_to_yaml.rb +52 -0
  32. data/lib/tb/cmd_unnest.rb +118 -0
  33. data/lib/tb/cmdmain.rb +24 -20
  34. data/lib/tb/cmdtop.rb +33 -25
  35. data/lib/tb/cmdutil.rb +26 -66
  36. data/lib/tb/csv.rb +46 -34
  37. data/lib/tb/enum.rb +294 -0
  38. data/lib/tb/enumerable.rb +198 -7
  39. data/lib/tb/enumerator.rb +73 -0
  40. data/lib/tb/fieldset.rb +27 -19
  41. data/lib/tb/fileenumerator.rb +365 -0
  42. data/lib/tb/json.rb +50 -0
  43. data/lib/tb/pager.rb +6 -6
  44. data/lib/tb/pairs.rb +227 -0
  45. data/lib/tb/pnm.rb +23 -22
  46. data/lib/tb/reader.rb +52 -49
  47. data/lib/tb/record.rb +48 -19
  48. data/lib/tb/revcmp.rb +38 -0
  49. data/lib/tb/ropen.rb +74 -57
  50. data/lib/tb/search.rb +25 -21
  51. data/lib/tb/tsv.rb +31 -34
  52. data/sample/excel2csv +24 -20
  53. data/sample/poi-xls2csv.rb +24 -20
  54. data/sample/poi-xls2csv.sh +22 -18
  55. data/sample/tbplot +185 -127
  56. data/test-all-cov.rb +3 -3
  57. data/test-all.rb +1 -1
  58. data/test/test_basic.rb +26 -10
  59. data/test/test_catreader.rb +7 -6
  60. data/test/test_cmd_cat.rb +32 -0
  61. data/test/test_cmd_consecutive.rb +10 -0
  62. data/test/test_cmd_crop.rb +4 -4
  63. data/test/test_cmd_cross.rb +16 -4
  64. data/test/test_cmd_git_log.rb +46 -0
  65. data/test/test_cmd_help.rb +17 -12
  66. data/test/test_cmd_join.rb +21 -1
  67. data/test/test_cmd_ls.rb +3 -4
  68. data/test/test_cmd_mheader.rb +17 -11
  69. data/test/test_cmd_nest.rb +49 -0
  70. data/test/test_cmd_sort.rb +15 -0
  71. data/test/test_cmd_tar_tvf.rb +281 -0
  72. data/test/{test_cmd_csv.rb → test_cmd_to_csv.rb} +35 -21
  73. data/test/{test_cmd_json.rb → test_cmd_to_json.rb} +31 -3
  74. data/test/{test_cmd_pnm.rb → test_cmd_to_pnm.rb} +2 -2
  75. data/test/{test_cmd_pp.rb → test_cmd_to_pp.rb} +4 -4
  76. data/test/{test_cmd_tsv.rb → test_cmd_to_tsv.rb} +4 -4
  77. data/test/{test_cmd_yaml.rb → test_cmd_to_yaml.rb} +3 -3
  78. data/test/test_cmd_unnest.rb +89 -0
  79. data/test/test_cmdtty.rb +19 -13
  80. data/test/test_enumerable.rb +83 -1
  81. data/test/test_fileenumerator.rb +265 -0
  82. data/test/test_json.rb +15 -0
  83. data/test/test_pager.rb +3 -4
  84. data/test/test_pairs.rb +122 -0
  85. data/test/test_pnm.rb +24 -24
  86. data/test/test_reader.rb +35 -13
  87. data/test/test_revcmp.rb +10 -0
  88. data/test/test_tbenum.rb +173 -0
  89. metadata +51 -23
  90. data/lib/tb/cmd_csv.rb +0 -42
  91. data/lib/tb/cmd_json.rb +0 -60
  92. data/lib/tb/cmd_pnm.rb +0 -43
  93. data/lib/tb/cmd_pp.rb +0 -70
  94. data/lib/tb/cmd_tsv.rb +0 -43
  95. 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 json [OPTS] [TABLE]
134
- tb yaml [OPTS] [TABLE]
135
- tb pp [OPTS] [TABLE]
136
- tb grep [OPTS] REGEXP [TABLE]
137
- tb gsub [OPTS] REGEXP STRING [TABLE]
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] [TABLE ...]
144
- tb group [OPTS] KEY-FIELD1,... [TABLE]
145
- tb cross [OPTS] HKEY-FIELD1,... VKEY-FIELD1,... [TABLE]
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 : show help message of tb command.
155
- csv : convert a table to CSV (Comma Separated Value).
156
- tsv : convert a table to TSV (Tab Separated Value).
157
- json : convert a table to JSON (JavaScript Object Notation).
158
- yaml : convert a table to YAML (YAML Ain't a Markup Language).
159
- pp : convert a table to pretty printed format.
160
- grep : search rows using regexp or ruby expression.
161
- gsub : substitute cells.
162
- sort : sort rows.
163
- cut : select columns.
164
- rename : rename field names.
165
- newfield : add a field.
166
- cat : concatenate tables vertically.
167
- join : concatenate tables horizontally as left/right/full natural join.
168
- group : group and aggregate rows.
169
- cross : create a contingency table.
170
- shape : show table size.
171
- mheader : collapse multi rows header.
172
- crop : extract rectangle in a table.
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 are met:
191
-
192
- (1) Redistributions of source code must retain the above copyright notice, this
193
- list of conditions and the following disclaimer.
194
- (2) Redistributions in binary form must reproduce the above copyright notice,
195
- this list of conditions and the following disclaimer in the documentation
196
- and/or other materials provided with the distribution.
197
- (3) The name of the author may not be used to endorse or promote products
198
- derived from this software without specific prior written permission.
199
-
200
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
201
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
202
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
203
- EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
204
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
205
- OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
206
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
207
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
208
- IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
209
- OF SUCH DAMAGE.
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 are met:
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 notice, this
9
- # list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- # 3. The name of the author may not be used to endorse or promote products
14
- # derived from this software without specific prior written permission.
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 OR IMPLIED
17
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
- # OF SUCH DAMAGE.
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-2011 Tanaka Akira <akr@fsij.org>
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 are met:
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 notice, this
9
- # list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- # 3. The name of the author may not be used to endorse or promote products
14
- # derived from this software without specific prior written permission.
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 OR IMPLIED
17
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
- # OF SUCH DAMAGE.
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-2011 Tanaka Akira <akr@fsij.org>
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 are met:
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 notice, this
9
- # list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- # 3. The name of the author may not be used to endorse or promote products
14
- # derived from this software without specific prior written permission.
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 OR IMPLIED
17
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
- # OF SUCH DAMAGE.
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 Enumerable
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.include?(recordid)
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.include? field
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.include? field
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.include? recordid
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
- # :call-seq:
902
- # table1.natjoin2(table2)
903
- def natjoin2(table2)
904
- table1 = self
905
- fields1 = table1.list_fields
906
- fields2 = table2.list_fields
907
- common_fields = fields1 & fields2
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
- result = Tb.new(fields1 | fields2)
916
- table1.each {|rec1|
917
- k = rec1.values_at(*common_fields)
918
- rec2_list = h[k]
919
- next if !rec2_list
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
- table1 = self
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: