red-arrow 0.4.1 → 0.8.0

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.
@@ -0,0 +1,391 @@
1
+ # Copyright 2017 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Arrow
16
+ class Slicer
17
+ def initialize(table)
18
+ @table = table
19
+ end
20
+
21
+ def [](column_name)
22
+ column = @table[column_name]
23
+ return nil if column.nil?
24
+ ColumnCondition.new(column)
25
+ end
26
+
27
+ def respond_to_missing?(name, include_private)
28
+ return true if self[name]
29
+ super
30
+ end
31
+
32
+ def method_missing(name, *args, &block)
33
+ if args.empty?
34
+ column_condition = self[name]
35
+ return column_condition if column_condition
36
+ end
37
+ super
38
+ end
39
+
40
+ class Condition
41
+ def evaluate
42
+ message = "Slicer::Condition must define \#evaluate: #{inspect}"
43
+ raise NotImplementedError.new(message)
44
+ end
45
+
46
+ def &(condition)
47
+ AndCondition.new(self, condition)
48
+ end
49
+
50
+ def |(condition)
51
+ OrCondition.new(self, condition)
52
+ end
53
+
54
+ def ^(condition)
55
+ XorCondition.new(self, condition)
56
+ end
57
+ end
58
+
59
+ class LogicalCondition < Condition
60
+ def initialize(condition1, condition2)
61
+ @condition1 = condition1
62
+ @condition2 = condition2
63
+ end
64
+
65
+ def evaluate
66
+ values1 = @condition1.evaluate.each
67
+ values2 = @condition2.evaluate.each
68
+ raw_array = []
69
+ begin
70
+ loop do
71
+ value1 = values1.next
72
+ value2 = values2.next
73
+ if value1.nil? or value2.nil?
74
+ raw_array << nil
75
+ else
76
+ raw_array << evaluate_value(value1, value2)
77
+ end
78
+ end
79
+ rescue StopIteration
80
+ end
81
+ BooleanArray.new(raw_array)
82
+ end
83
+ end
84
+
85
+ class AndCondition < LogicalCondition
86
+ private
87
+ def evaluate_value(value1, value2)
88
+ value1 and value2
89
+ end
90
+ end
91
+
92
+ class OrCondition < LogicalCondition
93
+ private
94
+ def evaluate_value(value1, value2)
95
+ value1 or value2
96
+ end
97
+ end
98
+
99
+ class XorCondition < LogicalCondition
100
+ private
101
+ def evaluate_value(value1, value2)
102
+ value1 ^ value2
103
+ end
104
+ end
105
+
106
+ class ColumnCondition < Condition
107
+ def initialize(column)
108
+ @column = column
109
+ end
110
+
111
+ def evaluate
112
+ data = @column.data
113
+ if data.n_chunks == 1
114
+ array = data.get_chunk(0)
115
+ if array.is_a?(BooleanArray)
116
+ array
117
+ else
118
+ array.cast(BooleanDataType.new)
119
+ end
120
+ else
121
+ raw_array = []
122
+ data.each_chunk do |chunk|
123
+ if chunk.is_a?(BooleanArray)
124
+ boolean_array = chunk
125
+ else
126
+ boolean_array = chunk.cast(BooleanDataType.new)
127
+ end
128
+ boolean_array.each do |value|
129
+ raw_array << value
130
+ end
131
+ end
132
+ BooleanArray.new(raw_array)
133
+ end
134
+ end
135
+
136
+ def !@
137
+ NotColumnCondition.new(@column)
138
+ end
139
+
140
+ def null?
141
+ self == nil
142
+ end
143
+
144
+ def ==(value)
145
+ EqualCondition.new(@column, value)
146
+ end
147
+
148
+ def !=(value)
149
+ NotEqualCondition.new(@column, value)
150
+ end
151
+
152
+ def <(value)
153
+ LessCondition.new(@column, value)
154
+ end
155
+
156
+ def <=(value)
157
+ LessEqualCondition.new(@column, value)
158
+ end
159
+
160
+ def >(value)
161
+ GreaterCondition.new(@column, value)
162
+ end
163
+
164
+ def >=(value)
165
+ GreaterEqualCondition.new(@column, value)
166
+ end
167
+
168
+ def select(&block)
169
+ SelectCondition.new(@column, block)
170
+ end
171
+
172
+ def reject(&block)
173
+ RejectCondition.new(@column, block)
174
+ end
175
+ end
176
+
177
+ class NotColumnCondition < Condition
178
+ def initialize(column)
179
+ @column = column
180
+ end
181
+
182
+ def evaluate
183
+ data = @column.data
184
+ raw_array = []
185
+ data.each_chunk do |chunk|
186
+ if chunk.is_a?(BooleanArray)
187
+ boolean_array = chunk
188
+ else
189
+ boolean_array = chunk.cast(BooleanDataType.new)
190
+ end
191
+ boolean_array.each do |value|
192
+ if value.nil?
193
+ raw_array << value
194
+ else
195
+ raw_array << !value
196
+ end
197
+ end
198
+ end
199
+ BooleanArray.new(raw_array)
200
+ end
201
+
202
+ def !@
203
+ ColumnCondition.new(@column)
204
+ end
205
+ end
206
+
207
+ class EqualCondition < Condition
208
+ def initialize(column, value)
209
+ @column = column
210
+ @value = value
211
+ end
212
+
213
+ def !@
214
+ NotEqualCondition.new(@column, @value)
215
+ end
216
+
217
+ def evaluate
218
+ case @value
219
+ when nil
220
+ raw_array = @column.collect(&:nil?)
221
+ BooleanArray.new(raw_array)
222
+ else
223
+ raw_array = @column.collect do |value|
224
+ if value.nil?
225
+ nil
226
+ else
227
+ @value == value
228
+ end
229
+ end
230
+ BooleanArray.new(raw_array)
231
+ end
232
+ end
233
+ end
234
+
235
+ class NotEqualCondition < Condition
236
+ def initialize(column, value)
237
+ @column = column
238
+ @value = value
239
+ end
240
+
241
+ def !@
242
+ EqualCondition.new(@column, @value)
243
+ end
244
+
245
+ def evaluate
246
+ case @value
247
+ when nil
248
+ raw_array = @column.collect do |value|
249
+ not value.nil?
250
+ end
251
+ BooleanArray.new(raw_array)
252
+ else
253
+ raw_array = @column.collect do |value|
254
+ if value.nil?
255
+ nil
256
+ else
257
+ @value != value
258
+ end
259
+ end
260
+ BooleanArray.new(raw_array)
261
+ end
262
+ end
263
+ end
264
+
265
+ class LessCondition < Condition
266
+ def initialize(column, value)
267
+ @column = column
268
+ @value = value
269
+ end
270
+
271
+ def !@
272
+ GreaterEqualCondition.new(@column, @value)
273
+ end
274
+
275
+ def evaluate
276
+ raw_array = @column.collect do |value|
277
+ if value.nil?
278
+ nil
279
+ else
280
+ @value > value
281
+ end
282
+ end
283
+ BooleanArray.new(raw_array)
284
+ end
285
+ end
286
+
287
+ class LessEqualCondition < Condition
288
+ def initialize(column, value)
289
+ @column = column
290
+ @value = value
291
+ end
292
+
293
+ def !@
294
+ GreaterCondition.new(@column, @value)
295
+ end
296
+
297
+ def evaluate
298
+ raw_array = @column.collect do |value|
299
+ if value.nil?
300
+ nil
301
+ else
302
+ @value >= value
303
+ end
304
+ end
305
+ BooleanArray.new(raw_array)
306
+ end
307
+ end
308
+
309
+ class GreaterCondition < Condition
310
+ def initialize(column, value)
311
+ @column = column
312
+ @value = value
313
+ end
314
+
315
+ def !@
316
+ LessEqualCondition.new(@column, @value)
317
+ end
318
+
319
+ def evaluate
320
+ raw_array = @column.collect do |value|
321
+ if value.nil?
322
+ nil
323
+ else
324
+ @value < value
325
+ end
326
+ end
327
+ BooleanArray.new(raw_array)
328
+ end
329
+ end
330
+
331
+ class GreaterEqualCondition < Condition
332
+ def initialize(column, value)
333
+ @column = column
334
+ @value = value
335
+ end
336
+
337
+ def !@
338
+ LessCondition.new(@column, @value)
339
+ end
340
+
341
+ def evaluate
342
+ raw_array = @column.collect do |value|
343
+ if value.nil?
344
+ nil
345
+ else
346
+ @value <= value
347
+ end
348
+ end
349
+ BooleanArray.new(raw_array)
350
+ end
351
+ end
352
+
353
+ class SelectCondition < Condition
354
+ def initialize(column, block)
355
+ @column = column
356
+ @block = block
357
+ end
358
+
359
+ def !@
360
+ RejectCondition.new(@column, @block)
361
+ end
362
+
363
+ def evaluate
364
+ BooleanArray.new(@column.collect(&@block))
365
+ end
366
+ end
367
+
368
+ class RejectCondition < Condition
369
+ def initialize(column, block)
370
+ @column = column
371
+ @block = block
372
+ end
373
+
374
+ def !@
375
+ SelectCondition.new(@column, @block)
376
+ end
377
+
378
+ def evaluate
379
+ raw_array = @column.collect do |value|
380
+ evaluated_value = @block.call(value)
381
+ if evaluated_value.nil?
382
+ nil
383
+ else
384
+ not evaluated_value
385
+ end
386
+ end
387
+ BooleanArray.new(raw_array)
388
+ end
389
+ end
390
+ end
391
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright 2017-2018 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "time"
16
+
17
+ module Arrow
18
+ class TableFormatter
19
+ def initialize(table, options={})
20
+ @table = table
21
+ @options = options
22
+ end
23
+
24
+ def format
25
+ text = ""
26
+ columns = @table.columns
27
+ columns.each do |column|
28
+ text << "\t"
29
+ text << format_column_name(column)
30
+ end
31
+ text << "\n"
32
+
33
+ n_rows = @table.n_rows
34
+ return text if n_rows.zero?
35
+
36
+ border = @options[:border] || 10
37
+ n_digits = (Math.log10(n_rows) + 1).truncate
38
+ [border, n_rows].min.times do |i|
39
+ format_row(text, columns, i, n_digits)
40
+ end
41
+ return text if n_rows <= border
42
+
43
+ text << "...\n"
44
+ [border, n_rows - border].max.upto(n_rows - 1) do |i|
45
+ format_row(text, columns, i, n_digits)
46
+ end
47
+
48
+ text
49
+ end
50
+
51
+ private
52
+ FLOAT_N_DIGITS = 10
53
+ def format_column_name(column)
54
+ case column.data_type
55
+ when TimestampDataType
56
+ "%*s" % [Time.now.iso8601.size, column.name]
57
+ when FloatDataType, DoubleDataType
58
+ "%*s" % [FLOAT_N_DIGITS, column.name]
59
+ else
60
+ column.name
61
+ end
62
+ end
63
+
64
+ def format_row(text, columns, i, n_digits)
65
+ text << ("%*d" % [n_digits, i])
66
+ columns.each do |column|
67
+ text << "\t"
68
+ text << format_column_value(column, i)
69
+ end
70
+ text << "\n"
71
+ text
72
+ end
73
+
74
+ def format_column_value(column, i)
75
+ value = column[i]
76
+ case value
77
+ when Time
78
+ value.iso8601
79
+ when Float
80
+ "%*f" % [[column.name.size, FLOAT_N_DIGITS].max, value]
81
+ when Integer
82
+ "%*d" % [column.name.size, value]
83
+ else
84
+ "%-*s" % [column.name.size, value.to_s]
85
+ end
86
+ end
87
+ end
88
+ end