enumerable_lz 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +6 -0
- data/LICENSE.txt +1 -1
- data/README.md +26 -9
- data/lib/enumerable_lz.rb +42 -2
- data/lib/enumerable_lz/enumerable_ex.rb +50 -8
- data/lib/enumerable_lz/filter.rb +68 -17
- data/lib/enumerable_lz/filter_18.rb +82 -59
- data/lib/enumerable_lz/filter_mrb.rb +37 -14
- data/lib/enumerable_lz/transform.rb +55 -6
- data/lib/enumerable_lz/transform_18.rb +66 -37
- data/lib/enumerable_lz/transform_mrb.rb +32 -5
- data/test/test_filter.rb +31 -10
- data/test/test_transform.rb +24 -2
- metadata +28 -34
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8ad8aeb48998541b0d13a8e20a63aa5d2b6af5ba
|
4
|
+
data.tar.gz: 7f66a110548e37e864bee992327c67ad36580dd4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b7847ff329ce9a00831d66525d7dc5f91fadbe4f33a3a249dcc1cea959eaef37795ab0648e127be80b26ae1a3a83d913a304aa9670b2f76d7269b379a5f9fcbe
|
7
|
+
data.tar.gz: 5511760da227ab917f450a4c9c2af7475d5e88923a374de2d8b1a780edb909fcc1b30b81d9b3c79f5c560e881c22c9a831a4ac900c80f4e1f49487ace01aa745
|
data/ChangeLog
CHANGED
@@ -14,3 +14,9 @@
|
|
14
14
|
|
15
15
|
* Improve performance much more
|
16
16
|
|
17
|
+
== 0.1.5 / 2014-01-08
|
18
|
+
|
19
|
+
* Add `filter.with_index` and `transform.with_index` feature
|
20
|
+
* Add `filter.with_initializer` feature (and obsolete `filter_with_initproc` method)
|
21
|
+
* Add support for Ruby 2.0.0/2.1.0
|
22
|
+
* Improve performance
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License
|
2
2
|
|
3
|
-
Copyright (c) 2011 GOTOH Shunsuke (@antimon2)
|
3
|
+
Copyright (c) 2011,2014 GOTOH Shunsuke (@antimon2)
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -9,17 +9,32 @@ Also it provides lazy equivalents of some methods in `Enumerable`.
|
|
9
9
|
When require 'enumerable_lz', these lazy methods are provided:
|
10
10
|
|
11
11
|
* `Enumerable#filter`
|
12
|
-
* `Enumerable#filter_with_initproc`
|
13
12
|
* `Enumerable#transform`
|
14
13
|
|
15
|
-
|
14
|
+
And some method-chains are provided:
|
15
|
+
|
16
|
+
* `Enumerable#filter.with_index`
|
17
|
+
* `Enumerable#filter.with_initializer`
|
18
|
+
* `Enumerable#transform.with_index`
|
19
|
+
|
20
|
+
For example (in Ruby 1.9.x or greater):
|
16
21
|
|
17
22
|
require 'enumerable_lz'
|
18
23
|
require 'prime'
|
19
|
-
|
24
|
+
|
20
25
|
(1..Float::INFINITY).transform{|n|n**2+1}.filter{|m|m.prime?}.take(100)
|
21
26
|
# => [2, 5, ... , 682277, 739601] for a few msec.
|
22
27
|
|
28
|
+
Prime.filter.with_index{|q,i|i.odd?}.take(10)
|
29
|
+
# => [3, 7, 13, 19, 29, 37, 43, 53, 61, 71]
|
30
|
+
|
31
|
+
Prime.transform.with_index{|q,i|[q,i]}.take(10)
|
32
|
+
# => [[2, 0], [3, 1], [5, 2], [7, 3], [11, 4], [13, 5], [17, 6], [19, 7], [23, 8], [29, 9]]
|
33
|
+
|
34
|
+
# especially, when calling transform.with_index without a block
|
35
|
+
Prime.transform.with_index.take(10)
|
36
|
+
# => [[2, 0], [3, 1], [5, 2], [7, 3], [11, 4], [13, 5], [17, 6], [19, 7], [23, 8], [29, 9]]
|
37
|
+
|
23
38
|
|
24
39
|
## Expanded Usage
|
25
40
|
|
@@ -37,7 +52,7 @@ When require 'enumerable_lz/enumerable_ex', some lazy methods equivalents to ori
|
|
37
52
|
* `Enumerable#take_while_lz`
|
38
53
|
|
39
54
|
|
40
|
-
For example (in Ruby 1.9.x):
|
55
|
+
For example (in Ruby 1.9.x or greater):
|
41
56
|
|
42
57
|
require 'enumerable_lz'
|
43
58
|
require 'enumerable_lz/enumerable_ex'
|
@@ -51,10 +66,12 @@ These expanded methods are inplemented with fundamental filter and transformatio
|
|
51
66
|
|
52
67
|
## Supported Rubies
|
53
68
|
|
54
|
-
* Ruby 1.
|
55
|
-
* Ruby
|
56
|
-
*
|
57
|
-
*
|
69
|
+
* Ruby 2.1.0 (testing 2.1.0-p0)
|
70
|
+
* Ruby 2.0.0 (testing 2.0.0-p247)
|
71
|
+
* Ruby 1.9.x (testing 1.9.3-p448)
|
72
|
+
* Ruby 1.8.7 (testing 1.8.7-p358)
|
73
|
+
* JRuby (testing 1.7.2)
|
74
|
+
* MacRuby (testing 0.12)
|
58
75
|
|
59
76
|
## Installation
|
60
77
|
|
@@ -64,6 +81,6 @@ These expanded methods are inplemented with fundamental filter and transformatio
|
|
64
81
|
## License
|
65
82
|
|
66
83
|
The MIT License
|
67
|
-
Copyright (c) 2011 GOTOH Shunsuke (@antimon2)
|
84
|
+
Copyright (c) 2011, 2014 GOTOH Shunsuke (@antimon2)
|
68
85
|
|
69
86
|
Please see [LICENSE.txt](LICENSE.txt) for details.
|
data/lib/enumerable_lz.rb
CHANGED
@@ -11,8 +11,48 @@ else
|
|
11
11
|
require File.dirname(__FILE__)+'/enumerable_lz/transform_18'
|
12
12
|
end
|
13
13
|
|
14
|
+
# add {#filter} and {#transform} methods.
|
14
15
|
module Enumerable
|
16
|
+
# @!group Fundamental Method Summary
|
17
|
+
|
18
|
+
# Filter by pattern or block
|
19
|
+
# @yield [el]
|
20
|
+
# @overload filter(&block)
|
21
|
+
# filter by block
|
22
|
+
# @yield [el] filterring block.
|
23
|
+
# @yieldparam el each element of original Enumerable
|
24
|
+
# @yieldreturn [Boolean]
|
25
|
+
# @return [Enumerator::Filter]
|
26
|
+
# @overload filter(pattern)
|
27
|
+
# filter by pattern
|
28
|
+
# @param [#===] pattern filterring pattern. (uses === method)
|
29
|
+
# @return [Enumerator::Filter]
|
30
|
+
# @return [Enumerator::Filter]
|
31
|
+
def filter pattern = nil, &block
|
32
|
+
Enumerator::Filter.new self, pattern||block
|
33
|
+
end
|
34
|
+
|
35
|
+
# @yield [el]
|
36
|
+
# @deprecated Use filter.with_initializer instead of this method
|
37
|
+
# @see Enumerator::Filter#with_initializer
|
38
|
+
# @return [Enumerator::Filter]
|
39
|
+
def filter_with_initproc init_proc, pattern = nil, &block
|
40
|
+
filter.with_initializer init_proc, pattern = nil, &block
|
41
|
+
end
|
42
|
+
|
43
|
+
# Transform by block
|
44
|
+
# @yield [el] transform block.
|
45
|
+
# @yieldparam el each element of original Enumerable
|
46
|
+
# @yieldreturn [Object]
|
47
|
+
# @return [Enumerator::Transform]
|
48
|
+
def transform &block
|
49
|
+
Enumerator::Transform.new self, &block
|
50
|
+
end
|
51
|
+
|
52
|
+
# @!endgroup
|
53
|
+
|
54
|
+
# @private
|
15
55
|
module EnumerableLz
|
16
|
-
VERSION = "0.1.
|
56
|
+
VERSION = "0.1.5"
|
17
57
|
end
|
18
|
-
end
|
58
|
+
end
|
@@ -1,49 +1,91 @@
|
|
1
1
|
require File.expand_path('..', __FILE__)
|
2
2
|
|
3
3
|
module Enumerable
|
4
|
+
# @!group Expanded Method Summary
|
5
|
+
|
6
|
+
# lazy equivalent of `Enumerable#select`
|
7
|
+
# @yield [el]
|
8
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
9
|
+
# @return [Enumerator::Filter]
|
4
10
|
def select_lz &block
|
5
11
|
filter &block
|
6
12
|
end
|
7
|
-
|
8
13
|
alias :find_all_lz :select_lz
|
9
14
|
|
15
|
+
# lazy equivalent of `Enumerable#reject`
|
16
|
+
# @yield [el]
|
17
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
18
|
+
# @return [Enumerator::Filter]
|
10
19
|
def reject_lz &block
|
11
20
|
filter {|e|!block.call(e)}
|
12
21
|
end
|
13
22
|
|
23
|
+
# lazy equivalent of `Enumerable#grep`
|
24
|
+
# @yield [el]
|
25
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
26
|
+
# @overload grep_lz(pattern)
|
27
|
+
# @return [Enumerator::Filter]
|
28
|
+
# @overload grep_lz(pattern, &block)
|
29
|
+
# @yield [el]
|
30
|
+
# @return [Enumerator::Transform]
|
31
|
+
# @return [Enumerator::Filter, Enumerator::Transform]
|
14
32
|
def grep_lz pattern, &block
|
15
33
|
enum = filter pattern
|
16
34
|
block_given? ? enum.transform(&block) : enum
|
17
35
|
end
|
18
36
|
|
19
|
-
|
37
|
+
# @!method map_lz(&block)
|
38
|
+
# lazy equivalent of `Enumerable#map`
|
39
|
+
# @yield [el]
|
40
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
41
|
+
# @return [Enumerator::Transform]
|
42
|
+
self.__send__(:alias_method, :map_lz, :transform)
|
20
43
|
alias :collect_lz :map_lz
|
21
44
|
|
45
|
+
# lazy equivalent of `Enumerable#drop`
|
46
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
47
|
+
# @return [Enumerator::Filter]
|
22
48
|
def drop_lz n
|
23
49
|
raise ArgumentError, "attempt to take negative size" if n < 0
|
24
50
|
# each_with_index.filter{|el,idx|idx >= n}.transform{|el,idx|el}
|
25
|
-
cnt = 0
|
26
|
-
filter_with_initproc(Proc.new{cnt=0}) {|el| (cnt+=1) > n}
|
51
|
+
# cnt = 0
|
52
|
+
# filter_with_initproc(Proc.new{cnt=0}) {|el| (cnt+=1) > n}
|
53
|
+
filter.with_index {|el, i| i >= n}
|
27
54
|
end
|
28
55
|
|
56
|
+
# lazy equivalent of `Enumerable#drop_while`
|
57
|
+
# @yield [el]
|
58
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
59
|
+
# @return [Enumerator::Filter]
|
29
60
|
def drop_while_lz &block
|
30
61
|
return self if !block_given?
|
31
62
|
flg = false
|
32
|
-
filter_with_initproc(Proc.new{flg=false}) {|el|flg || (!block.call(el) ? flg = true : false)}
|
63
|
+
# filter_with_initproc(Proc.new{flg=false}) {|el|flg || (!block.call(el) ? flg = true : false)}
|
64
|
+
filter.with_initializer(Proc.new{flg=false}) {|el|flg || (!block.call(el) ? flg = true : false)}
|
33
65
|
end
|
34
66
|
|
67
|
+
# lazy equivalent of `Enumerable#take`
|
68
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
69
|
+
# @return [Enumerator::Filter]
|
35
70
|
def take_lz n
|
36
71
|
raise ArgumentError, "attempt to take negative size" if n < 0
|
37
72
|
# each_with_index.filter{|el,idx|throw :do_break if idx >= n;true}.transform{|el,idx|el}
|
38
|
-
cnt = 0
|
39
|
-
filter_with_initproc(Proc.new{cnt=0}) {|el| throw :do_break if (cnt+=1) > n;true}
|
73
|
+
# cnt = 0
|
74
|
+
# filter_with_initproc(Proc.new{cnt=0}) {|el| throw :do_break if (cnt+=1) > n;true}
|
75
|
+
filter.with_index {|el, i| throw :do_break if i >= n; true}
|
40
76
|
end
|
41
77
|
|
78
|
+
# lazy equivalent of `Enumerable#take_while`
|
79
|
+
# @yield [el]
|
80
|
+
# @note available only requiring "enumerable_lz/enumerable_ex"
|
81
|
+
# @return [Enumerator::Filter]
|
42
82
|
def take_while_lz &block
|
43
83
|
return self if !block_given?
|
44
|
-
filter {|el|throw :do_break unless block.call(el);true}
|
84
|
+
filter {|el|throw :do_break unless block.call(el); true}
|
45
85
|
end
|
46
86
|
|
87
|
+
# @!endgroup
|
88
|
+
|
47
89
|
# def zip_lz *lists
|
48
90
|
# enums = lists.map{|list|list.each rescue [].each}
|
49
91
|
# Enumerator.new do |y|
|
data/lib/enumerable_lz/filter.rb
CHANGED
@@ -1,21 +1,14 @@
|
|
1
|
-
# for Ruby1.9.x except for MacRuby
|
2
|
-
module Enumerable
|
3
|
-
def filter pattern = nil, &block
|
4
|
-
Filter.new self, pattern||block
|
5
|
-
end
|
6
|
-
|
7
|
-
def filter_with_initproc init_proc, pattern = nil, &block
|
8
|
-
Filter.new self, init_proc, pattern||block
|
9
|
-
end
|
1
|
+
# -- for Ruby1.9.x except for MacRuby
|
10
2
|
|
3
|
+
# add [Filter] and [Transform] classes.
|
4
|
+
class Enumerator
|
5
|
+
# Lazy Filterring Enumerator
|
11
6
|
class Filter < Enumerator
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
# @param [Enumerable] obj an Enumerable.
|
8
|
+
# @param [#===] the_filter filterring pattern or proc.
|
9
|
+
def initialize obj, the_filter=nil
|
15
10
|
@org_enum = obj
|
16
|
-
@init_block = init_block unless init_block.nil?
|
17
11
|
super() do |y|
|
18
|
-
@init_block.call unless @init_block.nil?
|
19
12
|
compiled_filter = @filter.nil? ? Proc.new{true} : lambda{|f|
|
20
13
|
break f[0] if f.size==1
|
21
14
|
codes = f.size.times.map do |idx|
|
@@ -32,6 +25,9 @@ module Enumerable
|
|
32
25
|
filter! the_filter if the_filter
|
33
26
|
end
|
34
27
|
|
28
|
+
# Apply filter pattern/block and return self. (bang method of filter)
|
29
|
+
# @yield [el]
|
30
|
+
# @return [Filter] self
|
35
31
|
def filter! pattern=nil, &block
|
36
32
|
@filter||=[]
|
37
33
|
if pattern.is_a? Array
|
@@ -42,9 +38,15 @@ module Enumerable
|
|
42
38
|
self
|
43
39
|
end
|
44
40
|
|
45
|
-
#[override]
|
41
|
+
# [override] for performance
|
42
|
+
# @yield [el]
|
43
|
+
# @overload filter(&block)
|
44
|
+
# @yield [el]
|
45
|
+
# @overload filter(pattern)
|
46
|
+
# @param [#===] pattern
|
47
|
+
# @see Enumerable#filter Enumerable#filter
|
48
|
+
# @return [Filter]
|
46
49
|
def filter pattern=nil, &block
|
47
|
-
return super unless @init_block.nil?
|
48
50
|
# clone.filter! pattern, &block
|
49
51
|
patterns = @filter.nil? ? [] : @filter.clone
|
50
52
|
if pattern.is_a? Array
|
@@ -55,6 +57,33 @@ module Enumerable
|
|
55
57
|
Filter.new @org_enum, patterns
|
56
58
|
end
|
57
59
|
|
60
|
+
# @overload with_initializer(init_proc, &block)
|
61
|
+
# filter by block with initializer proc.
|
62
|
+
# @param [#call] init_proc initializer proc. (uses .call method)
|
63
|
+
# @yield filterring block.
|
64
|
+
# @return [Filter]
|
65
|
+
# @overload with_initializer(init_proc, pattern)
|
66
|
+
# filter by pattern with initializer proc.
|
67
|
+
# @param [#call] init_proc initializer proc. (uses .call method)
|
68
|
+
# @param [#===] pattern filterring pattern. (uses === method)
|
69
|
+
# @return [Filter]
|
70
|
+
# @return [Filter]
|
71
|
+
def with_initializer init_proc, pattern = nil, &block
|
72
|
+
src_enum = @filter.nil? ? @org_enum : self
|
73
|
+
FilterWithInitializer.new src_enum, init_proc, pattern||block
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param [Numeric] offset offset.
|
77
|
+
# @yield [el, i]
|
78
|
+
# @return [Filter]
|
79
|
+
def with_index offset=0, &block
|
80
|
+
raise ArgumentError, "tried to call filter.with_index without a block" unless block_given?
|
81
|
+
i = offset - 1
|
82
|
+
with_initializer(Proc.new{i = offset - 1}) do |el|
|
83
|
+
block.call(el, i += 1)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
58
87
|
private
|
59
88
|
def conv_proc pattern
|
60
89
|
case pattern
|
@@ -65,9 +94,31 @@ module Enumerable
|
|
65
94
|
end
|
66
95
|
end
|
67
96
|
end
|
97
|
+
|
98
|
+
# @api private
|
99
|
+
class FilterWithInitializer < Filter
|
100
|
+
def initialize obj, init_block, the_filter = nil
|
101
|
+
super obj, the_filter
|
102
|
+
@initializer = init_block
|
103
|
+
end
|
104
|
+
|
105
|
+
def each &block
|
106
|
+
return self unless block_given?
|
107
|
+
@initializer.call
|
108
|
+
super &block
|
109
|
+
end
|
110
|
+
|
111
|
+
# @see Enumerable#filter Enumerable#filter
|
112
|
+
# @return [Filter]
|
113
|
+
def filter pattern=nil, &block
|
114
|
+
Filter.new self, pattern||block
|
115
|
+
end
|
116
|
+
end
|
117
|
+
private_constant :FilterWithInitializer if self.respond_to? :private_constant
|
68
118
|
end
|
69
|
-
#against the Bug on JRuby <1.6.2
|
119
|
+
# against the Bug on JRuby < 1.6.2
|
70
120
|
if !(Proc.new{true}===true)
|
121
|
+
# @private
|
71
122
|
class Proc
|
72
123
|
alias :=== :call
|
73
124
|
end
|
@@ -1,76 +1,99 @@
|
|
1
1
|
# for Ruby1.8.7
|
2
|
+
|
2
3
|
module Enumerable
|
3
|
-
|
4
|
-
Filter
|
5
|
-
|
4
|
+
class Enumerator
|
5
|
+
class Filter < Enumerator
|
6
|
+
def initialize obj, the_filter=nil
|
7
|
+
filter! the_filter if the_filter
|
8
|
+
@org_enum = obj
|
9
|
+
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
11
|
+
def each &block
|
12
|
+
return self unless block_given?
|
13
|
+
# compiled_filter = (@filter||[Proc.new{true}]).inject do |r,f|
|
14
|
+
# Proc.new{|el| r[el] && f[el]}
|
15
|
+
# end
|
16
|
+
compiled_filter = @filter.nil? ? Proc.new{true} : lambda{|f|
|
17
|
+
break f[0] if f.size==1
|
18
|
+
codes = f.size.times.map do |idx|
|
19
|
+
"f[#{idx}][el]"
|
20
|
+
end
|
21
|
+
eval "Proc.new{|el|"+codes.join(" && ")+"}"
|
22
|
+
}.call(@filter)
|
23
|
+
catch :do_break do
|
24
|
+
@org_enum.each do |el|
|
25
|
+
block.call(el) if compiled_filter[el]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
10
30
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
31
|
+
def filter! pattern=nil, &block
|
32
|
+
@filter||=[]
|
33
|
+
if pattern.is_a? Array
|
34
|
+
pattern.each{|el| @filter << conv_proc(el)}
|
35
|
+
else
|
36
|
+
@filter << conv_proc(pattern || block)
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
19
40
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
codes = f.size.times.map do |idx|
|
29
|
-
"f[#{idx}][el]"
|
41
|
+
#[override]
|
42
|
+
def filter pattern=nil, &block
|
43
|
+
# clone.filter! pattern, &block
|
44
|
+
patterns = @filter.nil? ? [] : @filter.clone
|
45
|
+
if pattern.is_a? Array
|
46
|
+
patterns.push(*pattern)
|
47
|
+
else
|
48
|
+
patterns << (pattern || block)
|
30
49
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
50
|
+
Filter.new @org_enum, patterns
|
51
|
+
end
|
52
|
+
|
53
|
+
def with_initializer init_proc, pattern = nil, &block
|
54
|
+
src_enum = @filter.nil? ? @org_enum : self
|
55
|
+
FilterWithInitializer.new src_enum, init_proc, pattern||block
|
56
|
+
end
|
57
|
+
|
58
|
+
#[override]
|
59
|
+
def with_index offset=0, &block
|
60
|
+
raise ArgumentError, "tried to call filter.with_index without a block" unless block_given?
|
61
|
+
i = offset - 1
|
62
|
+
with_initializer(Proc.new{i = offset - 1}) do |el|
|
63
|
+
block.call(el, i += 1)
|
36
64
|
end
|
37
65
|
end
|
38
|
-
self
|
39
|
-
end
|
40
66
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
67
|
+
private
|
68
|
+
def conv_proc pattern
|
69
|
+
case pattern
|
70
|
+
when nil
|
71
|
+
Proc.new{true}
|
72
|
+
when Proc
|
73
|
+
pattern
|
74
|
+
else
|
75
|
+
pattern.respond_to?(:to_proc) ? pattern.to_proc : Proc.new{|el|pattern===el}
|
76
|
+
end
|
47
77
|
end
|
48
|
-
self
|
49
78
|
end
|
50
79
|
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
80
|
+
# private
|
81
|
+
class FilterWithInitializer < Filter
|
82
|
+
def initialize obj, init_block, the_filter = nil
|
83
|
+
super obj, the_filter
|
84
|
+
@initializer = init_block
|
85
|
+
end
|
86
|
+
|
87
|
+
def each &block
|
88
|
+
return self unless block_given?
|
89
|
+
@initializer.call
|
90
|
+
super &block
|
60
91
|
end
|
61
|
-
Filter.new @org_enum, patterns
|
62
|
-
end
|
63
92
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
when nil
|
68
|
-
Proc.new{true}
|
69
|
-
when Proc
|
70
|
-
pattern
|
71
|
-
else
|
72
|
-
pattern.respond_to?(:to_proc) ? pattern.to_proc : Proc.new{|el|pattern===el}
|
93
|
+
#[override]
|
94
|
+
def filter pattern=nil, &block
|
95
|
+
Filter.new self, pattern||block
|
73
96
|
end
|
74
97
|
end
|
75
98
|
end
|
76
|
-
end
|
99
|
+
end
|
@@ -1,24 +1,15 @@
|
|
1
1
|
# for MacRuby
|
2
|
-
module Enumerable
|
3
|
-
def filter pattern = nil, &block
|
4
|
-
Filter.new self, pattern||block
|
5
|
-
end
|
6
|
-
|
7
|
-
def filter_with_initproc init_proc, pattern = nil, &block
|
8
|
-
Filter.new self, init_proc, pattern||block
|
9
|
-
end
|
10
2
|
|
3
|
+
class Enumerator
|
11
4
|
class Filter < Enumerator
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
TrueProc = Proc.new{true}
|
6
|
+
|
7
|
+
def initialize obj, the_filter = nil
|
15
8
|
@org_enum = obj
|
16
|
-
@init_block = init_block unless init_block.nil?
|
17
9
|
outer = self
|
18
10
|
super Class.new {
|
19
11
|
define_method :each do
|
20
12
|
return outer unless block_given?
|
21
|
-
init_block.call unless init_block.nil?
|
22
13
|
compiled_filter = outer.__send__(:compile_filter)
|
23
14
|
catch :do_break do
|
24
15
|
obj.each do |el|
|
@@ -50,10 +41,23 @@ module Enumerable
|
|
50
41
|
else
|
51
42
|
patterns<<(pattern || block)
|
52
43
|
end
|
53
|
-
return Filter.new @org_enum, @init_block, patterns unless @init_block.nil?
|
54
44
|
Filter.new @org_enum, patterns
|
55
45
|
end
|
56
46
|
|
47
|
+
def with_initializer init_proc, pattern = nil, &block
|
48
|
+
src_enum = @filter.nil? ? @org_enum : self
|
49
|
+
FilterWithInitializer.new src_enum, init_proc, pattern||block
|
50
|
+
end
|
51
|
+
|
52
|
+
#[override]
|
53
|
+
def with_index offset=0, &block
|
54
|
+
raise ArgumentError, "tried to call filter.with_index without a block" unless block_given?
|
55
|
+
i = offset - 1
|
56
|
+
patterns = @filter.nil? ? [] : @filter.clone
|
57
|
+
patterns << Proc.new{|el| block.call(el, i += 1)}
|
58
|
+
FilterWithInitializer.new @org_enum, Proc.new{i = offset - 1}, patterns
|
59
|
+
end
|
60
|
+
|
57
61
|
private
|
58
62
|
def conv_proc pattern
|
59
63
|
case pattern
|
@@ -74,4 +78,23 @@ module Enumerable
|
|
74
78
|
}.call(@filter)
|
75
79
|
end
|
76
80
|
end
|
81
|
+
|
82
|
+
# private
|
83
|
+
class FilterWithInitializer < Filter
|
84
|
+
def initialize obj, init_block, the_filter = nil
|
85
|
+
super obj, the_filter
|
86
|
+
@initializer = init_block
|
87
|
+
end
|
88
|
+
|
89
|
+
def each &block
|
90
|
+
return self unless block_given?
|
91
|
+
@initializer.call
|
92
|
+
super &block
|
93
|
+
end
|
94
|
+
|
95
|
+
#[override]
|
96
|
+
def filter pattern=nil, &block
|
97
|
+
Filter.new self, pattern||block
|
98
|
+
end
|
99
|
+
end
|
77
100
|
end
|
@@ -1,10 +1,11 @@
|
|
1
|
-
# for Ruby1.9.x except for MacRuby
|
2
|
-
module Enumerable
|
3
|
-
def transform &block
|
4
|
-
Transform.new self, &block
|
5
|
-
end
|
1
|
+
# -- for Ruby1.9.x except for MacRuby
|
6
2
|
|
3
|
+
# add [Filter] and [Transform] classes.
|
4
|
+
class Enumerator
|
5
|
+
# Lazy Transform Enumerator
|
7
6
|
class Transform < Enumerator
|
7
|
+
# @param [Enumerable] obj an Enumerable.
|
8
|
+
# @yield transform block.
|
8
9
|
def initialize obj, &transformer
|
9
10
|
@org_enum = obj
|
10
11
|
super() do |y|
|
@@ -16,13 +17,19 @@ module Enumerable
|
|
16
17
|
transform! &transformer if block_given?
|
17
18
|
end
|
18
19
|
|
20
|
+
# Apply another transformer block and return self. (bang method of transform)
|
21
|
+
# @yield [el] transform block.
|
22
|
+
# @return [Transform] self
|
19
23
|
def transform! &block
|
20
24
|
@transformer||=[]
|
21
25
|
@transformer << block if block_given?
|
22
26
|
self
|
23
27
|
end
|
24
28
|
|
25
|
-
#[override]
|
29
|
+
# [override] for performance
|
30
|
+
# @yield [el] transform block.
|
31
|
+
# @see Enumerable#transform Enumerable#transform
|
32
|
+
# @return [Transform]
|
26
33
|
def transform &block
|
27
34
|
# clone.transform! &block
|
28
35
|
cp = Transform.new @org_enum
|
@@ -32,6 +39,22 @@ module Enumerable
|
|
32
39
|
cp.transform! &block
|
33
40
|
end
|
34
41
|
|
42
|
+
# @yield [el, i]
|
43
|
+
# @overload with_index(offset=0, &block)
|
44
|
+
# @param [Numeric] offset offset.
|
45
|
+
# @yield [el, i]
|
46
|
+
# @return [Transform]
|
47
|
+
# @overload with_index(offset=0)
|
48
|
+
# @note same as with_index(offset) {|el, i| [el, i]}
|
49
|
+
# @param [Numeric] offset offset.
|
50
|
+
# @return [Transform]
|
51
|
+
# @return [Transform]
|
52
|
+
def with_index offset=0, &block
|
53
|
+
src_enum = @transformer.nil? || @transformer.size.zero? ? @org_enum : self
|
54
|
+
block ||= Proc.new{|el, i|[el, i]}
|
55
|
+
TransformWithIndex.new src_enum, offset, &block
|
56
|
+
end
|
57
|
+
|
35
58
|
private
|
36
59
|
def compile_transformer
|
37
60
|
return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
|
@@ -44,4 +67,30 @@ module Enumerable
|
|
44
67
|
}.call(@transformer)
|
45
68
|
end
|
46
69
|
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
class TransformWithIndex < Transform
|
73
|
+
def initialize obj, offset = 0, &transformer
|
74
|
+
@org_enum = obj
|
75
|
+
@transformer = transformer.nil? ? nil : [transformer]
|
76
|
+
@offset = offset
|
77
|
+
end
|
78
|
+
|
79
|
+
def each
|
80
|
+
return self unless block_given?
|
81
|
+
the_transformer = @transformer[0] || Proc.new{|el,i|el}
|
82
|
+
i = @offset - 1
|
83
|
+
@org_enum.each do |el|
|
84
|
+
yield the_transformer.call(el, i+=1)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# @see Enumerable#filter Enumerable#filter
|
89
|
+
# @return [Transform]
|
90
|
+
def transform &block
|
91
|
+
Transform.new self, &block
|
92
|
+
end
|
93
|
+
alias :transform! :transform
|
94
|
+
end
|
95
|
+
private_constant :TransformWithIndex if self.respond_to? :private_constant
|
47
96
|
end
|
@@ -1,50 +1,79 @@
|
|
1
1
|
# for Ruby1.8.7
|
2
2
|
module Enumerable
|
3
|
-
|
4
|
-
Transform
|
5
|
-
|
3
|
+
class Enumerator
|
4
|
+
class Transform < Enumerator
|
5
|
+
def initialize obj, &transformer
|
6
|
+
@org_enum = obj
|
7
|
+
transform! &transformer if block_given?
|
8
|
+
end
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def each &block
|
11
|
+
return self unless block_given?
|
12
|
+
the_transformer = compile_transformer
|
13
|
+
@org_enum.each do |el|
|
14
|
+
block.call the_transformer[el]
|
15
|
+
end
|
16
|
+
self
|
17
|
+
end
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
block.call the_transformer[el]
|
19
|
+
def transform! &block
|
20
|
+
@transformer||=[]
|
21
|
+
@transformer << block if block_given?
|
22
|
+
self
|
18
23
|
end
|
19
|
-
self
|
20
|
-
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
#[override]
|
26
|
+
def transform &block
|
27
|
+
# clone.transform! &block
|
28
|
+
cp = Transform.new @org_enum
|
29
|
+
@transformer.each do |org_block|
|
30
|
+
cp.transform! &org_block
|
31
|
+
end unless @transformer.nil?
|
32
|
+
cp.transform! &block
|
33
|
+
end
|
27
34
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
#[override]
|
36
|
+
def with_index offset=0, &block
|
37
|
+
src_enum = @transformer.nil? || @transformer.size.zero? ? @org_enum : self
|
38
|
+
block ||= Proc.new{|el, i|[el, i]}
|
39
|
+
TransformWithIndex.new src_enum, offset, &block
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def compile_transformer
|
44
|
+
return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
|
45
|
+
return @transformer[0] if @transformer.size==1
|
46
|
+
lambda{|t|
|
47
|
+
codes = t.size.times.inject "el" do |r,idx|
|
48
|
+
"t[#{idx}][#{r}]"
|
49
|
+
end
|
50
|
+
eval "Proc.new{|el|"+codes+"}"
|
51
|
+
}.call(@transformer)
|
52
|
+
end
|
36
53
|
end
|
37
54
|
|
38
|
-
private
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
55
|
+
# private
|
56
|
+
class TransformWithIndex < Transform
|
57
|
+
def initialize obj, offset = 0, &transformer
|
58
|
+
@org_enum = obj
|
59
|
+
@transformer = transformer.nil? ? nil : [transformer]
|
60
|
+
@offset = offset
|
61
|
+
end
|
62
|
+
|
63
|
+
def each
|
64
|
+
return self unless block_given?
|
65
|
+
the_transformer = @transformer[0] || Proc.new{|el,i|el}
|
66
|
+
i = @offset - 1
|
67
|
+
@org_enum.each do |el|
|
68
|
+
yield the_transformer.call(el, i+=1)
|
45
69
|
end
|
46
|
-
|
47
|
-
|
70
|
+
end
|
71
|
+
|
72
|
+
#[override]
|
73
|
+
def transform &block
|
74
|
+
Transform.new self, &block
|
75
|
+
end
|
76
|
+
alias :transform! :transform
|
48
77
|
end
|
49
78
|
end
|
50
79
|
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# for MacRuby
|
2
|
-
|
3
|
-
def transform &block
|
4
|
-
Transform.new self, &block
|
5
|
-
end
|
6
|
-
|
2
|
+
class Enumerator
|
7
3
|
class Transform < Enumerator
|
8
4
|
def initialize obj, &transformer
|
9
5
|
@org_enum = obj
|
@@ -36,6 +32,13 @@ module Enumerable
|
|
36
32
|
cp.transform! &block
|
37
33
|
end
|
38
34
|
|
35
|
+
#[override]
|
36
|
+
def with_index offset=0, &block
|
37
|
+
src_enum = @transformer.nil? || @transformer.size.zero? ? @org_enum : self
|
38
|
+
block ||= Proc.new{|el, i|[el, i]}
|
39
|
+
TransformWithIndex.new src_enum, offset, &block
|
40
|
+
end
|
41
|
+
|
39
42
|
private
|
40
43
|
def compile_transformer
|
41
44
|
return Proc.new{|a|a} if @transformer.nil? || @transformer.size==0
|
@@ -52,4 +55,28 @@ module Enumerable
|
|
52
55
|
# }.call(@transformer)
|
53
56
|
end
|
54
57
|
end
|
58
|
+
|
59
|
+
# private
|
60
|
+
class TransformWithIndex < Transform
|
61
|
+
def initialize obj, offset = 0, &transformer
|
62
|
+
@org_enum = obj
|
63
|
+
@transformer = transformer.nil? ? nil : [transformer]
|
64
|
+
@offset = offset
|
65
|
+
end
|
66
|
+
|
67
|
+
def each
|
68
|
+
return self unless block_given?
|
69
|
+
the_transformer = @transformer[0] || Proc.new{|el,i|el}
|
70
|
+
i = @offset - 1
|
71
|
+
@org_enum.each do |el|
|
72
|
+
yield the_transformer.call(el, i+=1)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#[override]
|
77
|
+
def transform &block
|
78
|
+
Transform.new self, &block
|
79
|
+
end
|
80
|
+
alias :transform! :transform
|
81
|
+
end
|
55
82
|
end
|
data/test/test_filter.rb
CHANGED
@@ -3,15 +3,17 @@ require 'enumerable_lz'
|
|
3
3
|
|
4
4
|
class FilterTest < Test::Unit::TestCase
|
5
5
|
def test_instance
|
6
|
-
|
6
|
+
filter_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Filter : Enumerator::Filter
|
7
|
+
enum = filter_class.new []
|
7
8
|
assert_not_nil(enum)
|
8
9
|
assert_kind_of(Enumerable, enum)
|
9
10
|
end
|
10
11
|
|
11
12
|
def test_filter_array
|
13
|
+
filter_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Filter : Enumerator::Filter
|
12
14
|
array = %w[Yes I have a number]
|
13
15
|
enum = array.filter{|letters|letters.size > 1}
|
14
|
-
assert_instance_of(
|
16
|
+
assert_instance_of(filter_class, enum)
|
15
17
|
assert_equal(%w[Yes have number], enum.to_a)
|
16
18
|
end
|
17
19
|
|
@@ -85,14 +87,15 @@ class FilterTest < Test::Unit::TestCase
|
|
85
87
|
assert_same(enum1, enum2)
|
86
88
|
end
|
87
89
|
|
88
|
-
def test_init_block
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
# def test_init_block
|
91
|
+
# range = -10..10
|
92
|
+
# cnt = 0
|
93
|
+
# init_pr = Proc.new{cnt = 0}
|
94
|
+
# filter_pr = Proc.new{(cnt+=1)<=10}
|
95
|
+
# # enum = Enumerator::FilterWithInitializer.new range, init_pr, filter_pr
|
96
|
+
# enum = Enumerator::FilterWithInitializer.new range, init_pr, filter_pr
|
97
|
+
# assert_equal([-10, -9, -8, -7, -6, -5, -4, -3, -2, -1], enum.to_a)
|
98
|
+
# end
|
96
99
|
|
97
100
|
def test_filter_with_initproc_1
|
98
101
|
range = -10..10
|
@@ -122,4 +125,22 @@ class FilterTest < Test::Unit::TestCase
|
|
122
125
|
enum = range.filter_with_initproc(init_pr) {|n|throw :do_break if (sum+=n)>100;true}
|
123
126
|
assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], enum.to_a)
|
124
127
|
end
|
128
|
+
|
129
|
+
def test_filetr_with_index
|
130
|
+
a = 0
|
131
|
+
b = (1..10).filter.with_index{|n,i|a=n;i.even?}.first
|
132
|
+
assert_equal([1, 1], [a, b])
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_filetr_with_index_2
|
136
|
+
a = 0
|
137
|
+
b = (1..10).filter.with_index(1){|n,i|a=n;i.even?}.first
|
138
|
+
assert_equal([2, 2], [a, b])
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_filetr_with_index_no_block
|
142
|
+
assert_raise(ArgumentError) do
|
143
|
+
(1..10).filter.with_index(2).take(2)
|
144
|
+
end
|
145
|
+
end
|
125
146
|
end
|
data/test/test_transform.rb
CHANGED
@@ -3,15 +3,17 @@ require 'enumerable_lz'
|
|
3
3
|
|
4
4
|
class TransformTest < Test::Unit::TestCase
|
5
5
|
def test_instance
|
6
|
-
|
6
|
+
transform_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Transform : Enumerator::Transform
|
7
|
+
enum = transform_class.new []
|
7
8
|
assert_not_nil(enum)
|
8
9
|
assert_kind_of(Enumerable, enum)
|
9
10
|
end
|
10
11
|
|
11
12
|
def test_transform_array
|
13
|
+
transform_class = RUBY_VERSION < "1.9.0" ? Enumerable::Enumerator::Transform : Enumerator::Transform
|
12
14
|
array = %w[Yes I have a number]
|
13
15
|
enum = array.transform{|letters|letters.swapcase}
|
14
|
-
assert_instance_of(
|
16
|
+
assert_instance_of(transform_class, enum)
|
15
17
|
assert_equal(%w[yES i HAVE A NUMBER], enum.to_a)
|
16
18
|
end
|
17
19
|
|
@@ -52,4 +54,24 @@ class TransformTest < Test::Unit::TestCase
|
|
52
54
|
enum2 = enum1.transform!
|
53
55
|
assert_same(enum1, enum2)
|
54
56
|
end
|
57
|
+
|
58
|
+
def test_transform_with_index
|
59
|
+
range = -10..10
|
60
|
+
a = 0
|
61
|
+
result = range.transform.with_index{|n,i|n+a=i}.take(10)
|
62
|
+
assert_equal(9, a)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_transform_with_index2
|
66
|
+
range = -10..10
|
67
|
+
a = 0
|
68
|
+
result = range.transform.with_index{|n,i|n+a=i}.take(10)
|
69
|
+
assert_equal([-10, -8, -6, -4, -2, 0, 2, 4, 6, 8], result)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_transform_with_index_no_block
|
73
|
+
range = -10..10
|
74
|
+
result = range.transform.with_index(2).filter{|n,i|n+i<10}.to_a
|
75
|
+
assert_equal([[-10, 2], [-9, 3], [-8, 4], [-7, 5], [-6, 6], [-5, 7], [-4, 8], [-3, 9], [-2, 10]], result)
|
76
|
+
end
|
55
77
|
end
|
metadata
CHANGED
@@ -1,28 +1,22 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: enumerable_lz
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.1.4
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- antimon2
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2011-05-07 00:00:00 +09:00
|
14
|
-
default_executable:
|
11
|
+
date: 2014-01-08 00:00:00.000000000 Z
|
15
12
|
dependencies: []
|
16
|
-
|
17
|
-
|
13
|
+
description: Add Enumerable#filter, Enumerable#transform and some equivalent methods
|
14
|
+
on Enumerable with suffix '_lz'.
|
18
15
|
email: antimon2.me@gmail.com
|
19
16
|
executables: []
|
20
|
-
|
21
17
|
extensions: []
|
22
|
-
|
23
18
|
extra_rdoc_files: []
|
24
|
-
|
25
|
-
files:
|
19
|
+
files:
|
26
20
|
- README.md
|
27
21
|
- LICENSE.txt
|
28
22
|
- ChangeLog
|
@@ -38,35 +32,35 @@ files:
|
|
38
32
|
- lib/enumerable_lz/transform_18.rb
|
39
33
|
- lib/enumerable_lz/transform_mrb.rb
|
40
34
|
- lib/enumerable_lz.rb
|
41
|
-
has_rdoc: true
|
42
35
|
homepage: https://github.com/antimon2/enumerable_lz
|
43
36
|
licenses: []
|
44
|
-
|
37
|
+
metadata: {}
|
45
38
|
post_install_message:
|
46
|
-
rdoc_options:
|
47
|
-
|
48
|
-
|
39
|
+
rdoc_options:
|
40
|
+
- --no-private
|
41
|
+
- --exclude
|
42
|
+
- (_mrb|_18)
|
43
|
+
require_paths:
|
49
44
|
- lib
|
50
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
- !ruby/object:Gem::Version
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - '>='
|
48
|
+
- !ruby/object:Gem::Version
|
55
49
|
version: 1.8.7
|
56
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
62
55
|
requirements: []
|
63
|
-
|
64
56
|
rubyforge_project: enumerable_lz
|
65
|
-
rubygems_version:
|
57
|
+
rubygems_version: 2.0.3
|
66
58
|
signing_key:
|
67
59
|
specification_version: 3
|
68
|
-
summary: Add Enumerable#filter, Enumerable#transform and some equivalent methods on
|
69
|
-
|
60
|
+
summary: Add Enumerable#filter, Enumerable#transform and some equivalent methods on
|
61
|
+
Enumerable with suffix '_lz'.
|
62
|
+
test_files:
|
70
63
|
- test/test_enumerable_ex.rb
|
71
64
|
- test/test_filter.rb
|
72
65
|
- test/test_transform.rb
|
66
|
+
has_rdoc: yard
|