keybreak 0.1.1 → 0.2.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.
- checksums.yaml +5 -13
- data/CHANGELOG.md +24 -0
- data/README.md +112 -58
- data/examples/count.rb +15 -12
- data/examples/empty_key.rb +54 -0
- data/examples/first_value.rb +13 -10
- data/examples/last_value.rb +12 -10
- data/examples/nested_sum.rb +15 -12
- data/examples/sum.rb +15 -12
- data/lib/keybreak/controller.rb +3 -1
- data/lib/keybreak/version.rb +1 -1
- data/lib/keybreak.rb +4 -0
- metadata +16 -14
checksums.yaml
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
NDM4YWQyZDM3NDgyMDlkM2NlMWE4NGM0NGQzNWM2ZDg5YWJkNDIwZA==
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 6b9146d36f6868c36c5a167ab3b61ce8b5bb85fd
|
|
4
|
+
data.tar.gz: 6e48f6323e51eb5713a6927d5d041d0d9582dd97
|
|
7
5
|
SHA512:
|
|
8
|
-
metadata.gz:
|
|
9
|
-
|
|
10
|
-
NTgyNDMxM2U5NGYwZGZkNmE2NTFkMjNlNWEyYWYwOWYxNjMwMGVhNDhmMDlh
|
|
11
|
-
YjZiNzcyOTQwMTBjYTc5NjJkYjBiOGQwZTM4NmYyZWI0ODNhZWE=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
ODM0ODkwNjk5MGIxNzMyMmU5ZWZhOWM0Mzc0N2QwOGZmZjkwZTExZmJkODRh
|
|
14
|
-
ZDViZTI4OGRjMmY0YmJiZTBkYTA1M2Q2ZTVjZDUxZDE1MTk1OGRiYTU4MmRm
|
|
15
|
-
NDJjZTBkMzRlNGNkNmRlYmQzNjU2MjBhZjY1Y2U1ODY3OGIxNGQ=
|
|
6
|
+
metadata.gz: 8306abbdd10e3fb401b58ad0a8aae8b191c985dcd06ce2a91cf0013246b52193df6b356a11eb393e3bf973464a7ccc3b5b8fdb281efed721cacd056681f310fa
|
|
7
|
+
data.tar.gz: 1a8f4dcc80d4914076482267d098401b64b0db04d01950921b8b859330dbf3744e434bf907cbee738e2cd94a0b5a50b5603903d6319554bc84d3d00fc7f09a14
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## 0.2.0 (2016-01-31)
|
|
2
|
+
|
|
3
|
+
Features:
|
|
4
|
+
|
|
5
|
+
- added :detection event
|
|
6
|
+
- rewrote all examples to read data from here document instead of DATA
|
|
7
|
+
|
|
8
|
+
## 0.1.1 (2016-01-29)
|
|
9
|
+
|
|
10
|
+
Features:
|
|
11
|
+
|
|
12
|
+
- added Ruby version in gemspec
|
|
13
|
+
|
|
14
|
+
Documentation:
|
|
15
|
+
|
|
16
|
+
- corrected comments in source files
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## 0.1.0 (2016-01-28)
|
|
20
|
+
|
|
21
|
+
Features:
|
|
22
|
+
|
|
23
|
+
- initial version
|
|
24
|
+
|
data/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Keybreak
|
|
2
2
|
|
|
3
|
-
Keybreak is a utility module for
|
|
3
|
+
Keybreak is a utility module for key break processing in Ruby.
|
|
4
4
|
|
|
5
5
|
## Introduction
|
|
6
6
|
|
|
7
7
|
### Key break processing
|
|
8
8
|
|
|
9
|
-
The "key break processing" means, assuming a sorted sequence of
|
|
9
|
+
The "key break processing" means, assuming a sorted sequence of records which can be grouped by a column,
|
|
10
10
|
doing the same process for each group.
|
|
11
11
|
|
|
12
12
|
The column used for the grouping is a "key".
|
|
@@ -19,11 +19,23 @@ it is called "key break".
|
|
|
19
19
|
A typical key break processing is counting the number of records for each key like below:
|
|
20
20
|
|
|
21
21
|
```ruby
|
|
22
|
+
RECORDS =<<EOD
|
|
23
|
+
a 1
|
|
24
|
+
b 2
|
|
25
|
+
b 3
|
|
26
|
+
c 4
|
|
27
|
+
c 5
|
|
28
|
+
c 6
|
|
29
|
+
d 7
|
|
30
|
+
e 8
|
|
31
|
+
e 9
|
|
32
|
+
EOD
|
|
33
|
+
|
|
22
34
|
count = 0
|
|
23
35
|
prev_key = nil
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
key = line.
|
|
37
|
+
RECORDS.each_line do |line|
|
|
38
|
+
key = line.split("\t")[0]
|
|
27
39
|
|
|
28
40
|
if !prev_key.nil? && key != prev_key
|
|
29
41
|
puts "#{prev_key}:#{count}"
|
|
@@ -37,8 +49,17 @@ end
|
|
|
37
49
|
if !prev_key.nil?
|
|
38
50
|
puts "#{prev_key}:#{count}"
|
|
39
51
|
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Note that you have to write "puts" once again after the iteration.
|
|
55
|
+
This is quite troublesome even for such a simple task, and is very my motivation.
|
|
56
|
+
|
|
57
|
+
With Keybreak module, the code goes like below:
|
|
40
58
|
|
|
41
|
-
|
|
59
|
+
```ruby
|
|
60
|
+
require "keybreak"
|
|
61
|
+
|
|
62
|
+
RECORDS =<<EOD
|
|
42
63
|
a 1
|
|
43
64
|
b 2
|
|
44
65
|
b 3
|
|
@@ -48,37 +69,18 @@ c 6
|
|
|
48
69
|
d 7
|
|
49
70
|
e 8
|
|
50
71
|
e 9
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Note that you have to write "puts" once again after the iteration.
|
|
54
|
-
This is quite troublesome even for such a simple task, and is very my motivation.
|
|
55
|
-
|
|
56
|
-
With Keybreak module, the code is like below:
|
|
57
|
-
|
|
58
|
-
```ruby
|
|
59
|
-
require "keybreak"
|
|
72
|
+
EOD
|
|
60
73
|
|
|
61
74
|
Keybreak.execute_with_controller do |c, count|
|
|
62
75
|
c.on(:keystart) {count = 0}
|
|
63
76
|
c.on(:keyend) {|key| puts "#{key}:#{count}"}
|
|
64
77
|
|
|
65
|
-
|
|
66
|
-
key = line.
|
|
78
|
+
RECORDS.each_line do |line|
|
|
79
|
+
key = line.split("\t")[0]
|
|
67
80
|
c.feed(key)
|
|
68
81
|
count += 1
|
|
69
82
|
end
|
|
70
83
|
end
|
|
71
|
-
|
|
72
|
-
__END__
|
|
73
|
-
a 1
|
|
74
|
-
b 2
|
|
75
|
-
b 3
|
|
76
|
-
c 4
|
|
77
|
-
c 5
|
|
78
|
-
c 6
|
|
79
|
-
d 7
|
|
80
|
-
e 8
|
|
81
|
-
e 9
|
|
82
84
|
```
|
|
83
85
|
|
|
84
86
|
You need to register event handlers as a key break consists of two events:
|
|
@@ -89,7 +91,7 @@ Then call feed() in your record loop.
|
|
|
89
91
|
The method holds current key, detects a key break, and calls the event handlers accordingly.
|
|
90
92
|
The block given to execute_with_controller makes sure to process the end of the last key.
|
|
91
93
|
|
|
92
|
-
In many cases, taking a functional approach such as Enumerable#map
|
|
94
|
+
In many cases, taking a functional approach such as Enumerable#map, Enumerable#slice_when, etc. would achieve the task simply.
|
|
93
95
|
But sometimes, a procedural code is needed.
|
|
94
96
|
Keybreak module may assist you to make your key break code simpler.
|
|
95
97
|
|
|
@@ -124,19 +126,10 @@ See [examples](https://github.com/hashimoton/keybreak/tree/master/examples) for
|
|
|
124
126
|
|
|
125
127
|
### Print first values for each key
|
|
126
128
|
|
|
127
|
-
Register a keystart handler which prints the given key and value.
|
|
129
|
+
Register a :keystart handler which prints the given key and value.
|
|
128
130
|
|
|
129
131
|
```ruby
|
|
130
|
-
|
|
131
|
-
c.on(:keystart) {|key, value| puts "#{key}:#{value}"}
|
|
132
|
-
|
|
133
|
-
DATA.each do |line|
|
|
134
|
-
key, value = line.chomp.split("\t")
|
|
135
|
-
c.feed(key, value)
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
__END__
|
|
132
|
+
RECORDS =<<EOD
|
|
140
133
|
a 1
|
|
141
134
|
b 2
|
|
142
135
|
b 3
|
|
@@ -146,6 +139,16 @@ c 6
|
|
|
146
139
|
d 7
|
|
147
140
|
e 8
|
|
148
141
|
e 9
|
|
142
|
+
EOD
|
|
143
|
+
|
|
144
|
+
Keybreak.execute_with_controller do |c|
|
|
145
|
+
c.on(:keystart) {|key, value| puts "#{key}:#{value}"}
|
|
146
|
+
|
|
147
|
+
RECORDS.each_line do |line|
|
|
148
|
+
key, value = line.split("\t")
|
|
149
|
+
c.feed(key, value)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
149
152
|
```
|
|
150
153
|
|
|
151
154
|
The result will be:
|
|
@@ -160,16 +163,16 @@ e:8
|
|
|
160
163
|
|
|
161
164
|
### Print last values for each key
|
|
162
165
|
|
|
163
|
-
Borrows
|
|
166
|
+
Borrows RECORDS from above example.
|
|
164
167
|
|
|
165
|
-
Register a keyend handler which prints the given key and value.
|
|
168
|
+
Register a :keyend handler which prints the given key and value.
|
|
166
169
|
|
|
167
170
|
```ruby
|
|
168
171
|
Keybreak.execute_with_controller do |c|
|
|
169
172
|
c.on(:keyend) {|key, value| puts "#{key}:#{value}"}
|
|
170
173
|
|
|
171
|
-
|
|
172
|
-
key, value = line.
|
|
174
|
+
RECORDS.each_line do |line|
|
|
175
|
+
key, value = line.split("\t")
|
|
173
176
|
c.feed(key, value)
|
|
174
177
|
end
|
|
175
178
|
end
|
|
@@ -195,8 +198,8 @@ Keybreak.execute_with_controller do |c, sum|
|
|
|
195
198
|
c.on(:keystart) {sum = 0}
|
|
196
199
|
c.on(:keyend) {|key| puts "#{key}:#{sum}"}
|
|
197
200
|
|
|
198
|
-
|
|
199
|
-
key, value = line.
|
|
201
|
+
RECORDS.each_line do |line|
|
|
202
|
+
key, value = line.split("\t")
|
|
200
203
|
c.feed(key)
|
|
201
204
|
sum += value.to_i
|
|
202
205
|
end
|
|
@@ -222,6 +225,18 @@ Give sub key handlers a set of primary key and sub key (an array for instance)
|
|
|
222
225
|
so that a primary key break is also detected as a sub key break.
|
|
223
226
|
|
|
224
227
|
```ruby
|
|
228
|
+
RECORDS =<<EOD
|
|
229
|
+
a a1 1
|
|
230
|
+
b b1 2
|
|
231
|
+
b b2 3
|
|
232
|
+
c c1 4
|
|
233
|
+
c c1 5
|
|
234
|
+
c c2 6
|
|
235
|
+
d d1 7
|
|
236
|
+
e e1 8
|
|
237
|
+
e e1 9
|
|
238
|
+
EOD
|
|
239
|
+
|
|
225
240
|
Keybreak.execute_with_controller do |c, sum|
|
|
226
241
|
c.on(:keystart) {sum = 0}
|
|
227
242
|
c.on(:keyend) {|key| puts "total #{key}:#{sum}"}
|
|
@@ -233,25 +248,14 @@ Keybreak.execute_with_controller do |c, sum|
|
|
|
233
248
|
sum += sub_sum
|
|
234
249
|
end
|
|
235
250
|
|
|
236
|
-
|
|
237
|
-
key, sub_key, value = line.
|
|
251
|
+
RECORDS.each_line do |line|
|
|
252
|
+
key, sub_key, value = line.split("\t")
|
|
238
253
|
sub_c.feed([key, sub_key])
|
|
239
254
|
c.feed(key)
|
|
240
255
|
sub_sum += value.to_i
|
|
241
256
|
end
|
|
242
257
|
end
|
|
243
258
|
end
|
|
244
|
-
|
|
245
|
-
__END__
|
|
246
|
-
a a1 1
|
|
247
|
-
b b1 2
|
|
248
|
-
b b2 3
|
|
249
|
-
c c1 4
|
|
250
|
-
c c1 5
|
|
251
|
-
c c2 6
|
|
252
|
-
d d1 7
|
|
253
|
-
e e1 8
|
|
254
|
-
e e1 9
|
|
255
259
|
```
|
|
256
260
|
|
|
257
261
|
The result will be:
|
|
@@ -271,6 +275,56 @@ e1:17
|
|
|
271
275
|
total e:17
|
|
272
276
|
```
|
|
273
277
|
|
|
278
|
+
### Print sum of values for each key where empty key means continuation
|
|
279
|
+
|
|
280
|
+
Sometimes we face the empty keys which mean to continue the value in the previous record.
|
|
281
|
+
The pivot table of MS Excel is an example.
|
|
282
|
+
Keybreak module can handle this case by providing a block for detecting a keybreak.
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
RECORDS =<<EOD
|
|
286
|
+
a a1 1
|
|
287
|
+
b b1 2
|
|
288
|
+
b2 3
|
|
289
|
+
c c1 4
|
|
290
|
+
5
|
|
291
|
+
c2 6
|
|
292
|
+
d d1 7
|
|
293
|
+
e e1 8
|
|
294
|
+
9
|
|
295
|
+
EOD
|
|
296
|
+
|
|
297
|
+
Keybreak.execute_with_controller do |c, sum|
|
|
298
|
+
c.on(:detection) {|key| !key.empty?}
|
|
299
|
+
c.on(:keystart) {sum = 0}
|
|
300
|
+
c.on(:keyend) {|key| puts "total #{key}:#{sum}"}
|
|
301
|
+
|
|
302
|
+
Keybreak.execute_with_controller do |sub_c, sub_sum|
|
|
303
|
+
sub_c.on(:detection) {|keys| !keys.all? {|key| key.empty?}}
|
|
304
|
+
sub_c.on(:keystart) {sub_sum = 0}
|
|
305
|
+
sub_c.on(:keyend) do |keys|
|
|
306
|
+
puts "#{keys[1]}:#{sub_sum}"
|
|
307
|
+
sum += sub_sum
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
RECORDS.each_line do |line|
|
|
311
|
+
key, sub_key, value = line.split("\t")
|
|
312
|
+
sub_c.feed([key, sub_key])
|
|
313
|
+
c.feed(key)
|
|
314
|
+
sub_sum += value.to_i
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
The result will be the same as the previous example.
|
|
321
|
+
|
|
322
|
+
By default, the below block is used for the key break detections.
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
{|key, prev_key| key != prev_key}
|
|
326
|
+
```
|
|
327
|
+
|
|
274
328
|
## Development
|
|
275
329
|
|
|
276
330
|
|
data/examples/count.rb
CHANGED
|
@@ -10,18 +10,7 @@
|
|
|
10
10
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
11
11
|
require "keybreak"
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
c.on(:keystart) {count = 0}
|
|
15
|
-
c.on(:keyend) {|key| puts "#{key}:#{count}"}
|
|
16
|
-
|
|
17
|
-
DATA.each do |line|
|
|
18
|
-
key = line.chomp.split("\t")[0]
|
|
19
|
-
c.feed(key)
|
|
20
|
-
count += 1
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
__END__
|
|
13
|
+
RECORDS =<<EOD
|
|
25
14
|
a 1
|
|
26
15
|
b 2
|
|
27
16
|
b 3
|
|
@@ -31,3 +20,17 @@ c 6
|
|
|
31
20
|
d 7
|
|
32
21
|
e 8
|
|
33
22
|
e 9
|
|
23
|
+
EOD
|
|
24
|
+
|
|
25
|
+
Keybreak.execute_with_controller do |c, count|
|
|
26
|
+
c.on(:keystart) {count = 0}
|
|
27
|
+
c.on(:keyend) {|key| puts "#{key}:#{count}"}
|
|
28
|
+
|
|
29
|
+
RECORDS.each_line do |line|
|
|
30
|
+
key = line.split("\t")[0]
|
|
31
|
+
c.feed(key)
|
|
32
|
+
count += 1
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# EOF
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# Print sum of values for each key where empty key means continuation
|
|
3
|
+
# =>
|
|
4
|
+
# a1:1
|
|
5
|
+
# total a:1
|
|
6
|
+
# b1:2
|
|
7
|
+
# b2:3
|
|
8
|
+
# total b:5
|
|
9
|
+
# c1:9
|
|
10
|
+
# c2:6
|
|
11
|
+
# total c:15
|
|
12
|
+
# d1:7
|
|
13
|
+
# total d:7
|
|
14
|
+
# e1:17
|
|
15
|
+
# total e:17
|
|
16
|
+
|
|
17
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
18
|
+
require "keybreak"
|
|
19
|
+
|
|
20
|
+
RECORDS =<<EOD
|
|
21
|
+
a a1 1
|
|
22
|
+
b b1 2
|
|
23
|
+
b2 3
|
|
24
|
+
c c1 4
|
|
25
|
+
5
|
|
26
|
+
c2 6
|
|
27
|
+
d d1 7
|
|
28
|
+
e e1 8
|
|
29
|
+
9
|
|
30
|
+
EOD
|
|
31
|
+
|
|
32
|
+
Keybreak.execute_with_controller do |c, sum|
|
|
33
|
+
c.on(:detection) {|key| !key.empty?}
|
|
34
|
+
c.on(:keystart) {sum = 0}
|
|
35
|
+
c.on(:keyend) {|key| puts "total #{key}:#{sum}"}
|
|
36
|
+
|
|
37
|
+
Keybreak.execute_with_controller do |sub_c, sub_sum|
|
|
38
|
+
sub_c.on(:detection) {|keys| !keys.all? {|key| key.empty?}}
|
|
39
|
+
sub_c.on(:keystart) {sub_sum = 0}
|
|
40
|
+
sub_c.on(:keyend) do |keys|
|
|
41
|
+
puts "#{keys[1]}:#{sub_sum}"
|
|
42
|
+
sum += sub_sum
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
RECORDS.each_line do |line|
|
|
46
|
+
key, sub_key, value = line.split("\t")
|
|
47
|
+
sub_c.feed([key, sub_key])
|
|
48
|
+
c.feed(key)
|
|
49
|
+
sub_sum += value.to_i
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# EOF
|
data/examples/first_value.rb
CHANGED
|
@@ -10,16 +10,7 @@
|
|
|
10
10
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
11
11
|
require "keybreak"
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
c.on(:keystart) {|key, value| puts "#{key}:#{value}"}
|
|
15
|
-
|
|
16
|
-
DATA.each do |line|
|
|
17
|
-
key, value = line.chomp.split("\t")
|
|
18
|
-
c.feed(key, value)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
__END__
|
|
13
|
+
RECORDS =<<EOD
|
|
23
14
|
a 1
|
|
24
15
|
b 2
|
|
25
16
|
b 3
|
|
@@ -29,3 +20,15 @@ c 6
|
|
|
29
20
|
d 7
|
|
30
21
|
e 8
|
|
31
22
|
e 9
|
|
23
|
+
EOD
|
|
24
|
+
|
|
25
|
+
Keybreak.execute_with_controller do |c|
|
|
26
|
+
c.on(:keystart) {|key, value| puts "#{key}:#{value}"}
|
|
27
|
+
|
|
28
|
+
RECORDS.each_line do |line|
|
|
29
|
+
key, value = line.split("\t")
|
|
30
|
+
c.feed(key, value)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#EOF
|
data/examples/last_value.rb
CHANGED
|
@@ -10,16 +10,7 @@
|
|
|
10
10
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
11
11
|
require "keybreak"
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
c.on(:keyend) {|key, value| puts "#{key}:#{value}"}
|
|
15
|
-
|
|
16
|
-
DATA.each do |line|
|
|
17
|
-
key, value = line.chomp.split("\t")
|
|
18
|
-
c.feed(key, value)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
__END__
|
|
13
|
+
RECORDS =<<EOD
|
|
23
14
|
a 1
|
|
24
15
|
b 2
|
|
25
16
|
b 3
|
|
@@ -29,3 +20,14 @@ c 6
|
|
|
29
20
|
d 7
|
|
30
21
|
e 8
|
|
31
22
|
e 9
|
|
23
|
+
EOD
|
|
24
|
+
|
|
25
|
+
Keybreak.execute_with_controller do |c|
|
|
26
|
+
c.on(:keyend) {|key, value| puts "#{key}:#{value}"}
|
|
27
|
+
|
|
28
|
+
RECORDS.each_line do |line|
|
|
29
|
+
key, value = line.split("\t")
|
|
30
|
+
c.feed(key, value)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
data/examples/nested_sum.rb
CHANGED
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
18
18
|
require "keybreak"
|
|
19
19
|
|
|
20
|
+
RECORDS =<<EOD
|
|
21
|
+
a a1 1
|
|
22
|
+
b b1 2
|
|
23
|
+
b b2 3
|
|
24
|
+
c c1 4
|
|
25
|
+
c c1 5
|
|
26
|
+
c c2 6
|
|
27
|
+
d d1 7
|
|
28
|
+
e e1 8
|
|
29
|
+
e e1 9
|
|
30
|
+
EOD
|
|
31
|
+
|
|
20
32
|
Keybreak.execute_with_controller do |c, sum|
|
|
21
33
|
c.on(:keystart) {sum = 0}
|
|
22
34
|
c.on(:keyend) {|key| puts "total #{key}:#{sum}"}
|
|
@@ -28,8 +40,8 @@ Keybreak.execute_with_controller do |c, sum|
|
|
|
28
40
|
sum += sub_sum
|
|
29
41
|
end
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
key, sub_key, value = line.
|
|
43
|
+
RECORDS.each_line do |line|
|
|
44
|
+
key, sub_key, value = line.split("\t")
|
|
33
45
|
sub_c.feed([key, sub_key])
|
|
34
46
|
c.feed(key)
|
|
35
47
|
sub_sum += value.to_i
|
|
@@ -37,13 +49,4 @@ Keybreak.execute_with_controller do |c, sum|
|
|
|
37
49
|
end
|
|
38
50
|
end
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
a a1 1
|
|
42
|
-
b b1 2
|
|
43
|
-
b b2 3
|
|
44
|
-
c c1 4
|
|
45
|
-
c c1 5
|
|
46
|
-
c c2 6
|
|
47
|
-
d d1 7
|
|
48
|
-
e e1 8
|
|
49
|
-
e e1 9
|
|
52
|
+
# EOF
|
data/examples/sum.rb
CHANGED
|
@@ -10,18 +10,7 @@
|
|
|
10
10
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
11
11
|
require "keybreak"
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
c.on(:keystart) {sum = 0}
|
|
15
|
-
c.on(:keyend) {|key| puts "#{key}:#{sum}"}
|
|
16
|
-
|
|
17
|
-
DATA.each do |line|
|
|
18
|
-
key, value = line.chomp.split("\t")
|
|
19
|
-
c.feed(key)
|
|
20
|
-
sum += value.to_i
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
__END__
|
|
13
|
+
RECORDS =<<EOD
|
|
25
14
|
a 1
|
|
26
15
|
b 2
|
|
27
16
|
b 3
|
|
@@ -31,3 +20,17 @@ c 6
|
|
|
31
20
|
d 7
|
|
32
21
|
e 8
|
|
33
22
|
e 9
|
|
23
|
+
EOD
|
|
24
|
+
|
|
25
|
+
Keybreak.execute_with_controller do |c, sum|
|
|
26
|
+
c.on(:keystart) {sum = 0}
|
|
27
|
+
c.on(:keyend) {|key| puts "#{key}:#{sum}"}
|
|
28
|
+
|
|
29
|
+
RECORDS.each_line do |line|
|
|
30
|
+
key, value = line.split("\t")
|
|
31
|
+
c.feed(key)
|
|
32
|
+
sum += value.to_i
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# EOF
|
data/lib/keybreak/controller.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Keybreak
|
|
|
11
11
|
@handlers = {}
|
|
12
12
|
@handlers[:keystart] = DO_NOTHING
|
|
13
13
|
@handlers[:keyend] = DO_NOTHING
|
|
14
|
+
@handlers[:detection] = KEY_CHANGED
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ module Keybreak
|
|
|
18
19
|
# Valid events are:
|
|
19
20
|
# :keystart
|
|
20
21
|
# :keyend
|
|
22
|
+
# :detection
|
|
21
23
|
def on(event, &block)
|
|
22
24
|
@handlers[event] = block
|
|
23
25
|
end
|
|
@@ -30,7 +32,7 @@ module Keybreak
|
|
|
30
32
|
# Use flush() to call the :keyend handler for the last fed key.
|
|
31
33
|
def feed(key, *values)
|
|
32
34
|
if @is_fed
|
|
33
|
-
if key
|
|
35
|
+
if @handlers[:detection].call(key, @key)
|
|
34
36
|
@handlers[:keyend].call(@key, *@values)
|
|
35
37
|
@key = key
|
|
36
38
|
@handlers[:keystart].call(key, *values)
|
data/lib/keybreak/version.rb
CHANGED
data/lib/keybreak.rb
CHANGED
|
@@ -9,6 +9,10 @@ module Keybreak
|
|
|
9
9
|
DO_NOTHING = Proc.new {}
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
# The default key break detector
|
|
13
|
+
KEY_CHANGED = Proc.new {|key, prev_key| key != prev_key}
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
# Executes the given block with a Controller instance.
|
|
13
17
|
# Within the block, register your key break handlers and feed keys from your data.
|
|
14
18
|
# Then the handlers will be called for all keys including the last key.
|
metadata
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: keybreak
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- hashimoton
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-01-
|
|
11
|
+
date: 2016-01-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - ~>
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '1.11'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - ~>
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.11'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - ~>
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '10.0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - ~>
|
|
38
|
+
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '10.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rspec
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- - ~>
|
|
45
|
+
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
47
|
version: '3.0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- - ~>
|
|
52
|
+
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '3.0'
|
|
55
55
|
description:
|
|
@@ -59,14 +59,16 @@ executables: []
|
|
|
59
59
|
extensions: []
|
|
60
60
|
extra_rdoc_files: []
|
|
61
61
|
files:
|
|
62
|
-
- .gitignore
|
|
63
|
-
- .rspec
|
|
64
|
-
- .travis.yml
|
|
62
|
+
- ".gitignore"
|
|
63
|
+
- ".rspec"
|
|
64
|
+
- ".travis.yml"
|
|
65
|
+
- CHANGELOG.md
|
|
65
66
|
- Gemfile
|
|
66
67
|
- LICENSE.txt
|
|
67
68
|
- README.md
|
|
68
69
|
- Rakefile
|
|
69
70
|
- examples/count.rb
|
|
71
|
+
- examples/empty_key.rb
|
|
70
72
|
- examples/first_value.rb
|
|
71
73
|
- examples/last_value.rb
|
|
72
74
|
- examples/nested_sum.rb
|
|
@@ -85,17 +87,17 @@ require_paths:
|
|
|
85
87
|
- lib
|
|
86
88
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
89
|
requirements:
|
|
88
|
-
- -
|
|
90
|
+
- - ">="
|
|
89
91
|
- !ruby/object:Gem::Version
|
|
90
92
|
version: 1.9.3
|
|
91
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
94
|
requirements:
|
|
93
|
-
- -
|
|
95
|
+
- - ">="
|
|
94
96
|
- !ruby/object:Gem::Version
|
|
95
97
|
version: '0'
|
|
96
98
|
requirements: []
|
|
97
99
|
rubyforge_project:
|
|
98
|
-
rubygems_version: 2.5.1
|
|
100
|
+
rubygems_version: 2.4.5.1
|
|
99
101
|
signing_key:
|
|
100
102
|
specification_version: 4
|
|
101
103
|
summary: Keybreak is a utility module for key break processing in Ruby.
|