enumerable_fu 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown
CHANGED
@@ -1,50 +1,84 @@
|
|
1
1
|
EnumerableFu
|
2
2
|
============
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
Lazy "filtering" and transforming
|
5
|
+
---------------------------------
|
6
6
|
|
7
|
-
|
7
|
+
EnumerableFu extends Enumerable with "lazy" versions of various common operations:
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
* `#selecting` selects elements that pass a test block (like `Enumerable#select`)
|
10
|
+
* `#rejecting` selects elements that fail a test block (like `Enumerable#reject`)
|
11
|
+
* `#collecting` applies a transforming block to each element (like `Enumerable#collect`)
|
12
|
+
* `#uniqing` discards duplicates (like `Enumerable#uniq`)
|
11
13
|
|
12
|
-
|
14
|
+
We say the "...ing" variants are "lazy", because they defer per-element processing until the result is used. They return Enumerable "result proxy" objects, rather than Arrays, and only perform the actual filtering (or transformation) as the result proxy is enumerated.
|
13
15
|
|
14
|
-
|
16
|
+
Perhaps an example would help. Consider the following snippet:
|
15
17
|
|
16
|
-
|
18
|
+
>> (1..10).collect { |x| puts "#{x}^2 = #{x*x}"; x*x }.take_while { |x| x < 20 }
|
19
|
+
1^2 = 1
|
20
|
+
2^2 = 4
|
21
|
+
3^2 = 9
|
22
|
+
4^2 = 16
|
23
|
+
5^2 = 25
|
24
|
+
6^2 = 36
|
25
|
+
7^2 = 49
|
26
|
+
8^2 = 64
|
27
|
+
9^2 = 81
|
28
|
+
10^2 = 100
|
29
|
+
=> [1, 4, 9, 16]
|
30
|
+
|
31
|
+
Here we use plain old `#collect` to square a bunch of numbers, and then grab the ones less than 20. We can do the same thing using `#collecting`, rather than `#collect`:
|
17
32
|
|
18
|
-
(1..
|
33
|
+
>> (1..10).collecting { |x| puts "#{x}^2 = #{x*x}"; x*x }.take_while { |x| x < 20 }
|
34
|
+
1^2 = 1
|
35
|
+
2^2 = 4
|
36
|
+
3^2 = 9
|
37
|
+
4^2 = 16
|
38
|
+
5^2 = 25
|
39
|
+
=> [1, 4, 9, 16]
|
19
40
|
|
20
|
-
|
41
|
+
Same result, but notice how only the first five inputs were ever squared; just enough to find the first result above 20.
|
21
42
|
|
22
|
-
|
43
|
+
Lazy pipelines
|
44
|
+
--------------
|
23
45
|
|
24
|
-
|
46
|
+
By combining two or more of the lazy operations provided by EnumerableFu, you can create an efficient "pipeline", e.g.
|
25
47
|
|
26
|
-
|
48
|
+
# enumerate all users
|
49
|
+
users = User.to_enum(:find_each)
|
27
50
|
|
28
|
-
|
51
|
+
# where first and last names start with the same letter
|
52
|
+
users = users.selecting { |u| u.first_name[0] == u.last_name[0] }
|
29
53
|
|
30
|
-
|
31
|
-
|
54
|
+
# grab their company (weeding out duplicates)
|
55
|
+
companies = users.collecting(&:company).uniqing
|
32
56
|
|
33
|
-
|
57
|
+
# resolve
|
58
|
+
companies.to_a #=> ["Disney"]
|
59
|
+
|
60
|
+
Because each processing step proceeds in parallel, without creation of intermediate collections (Arrays), you can efficiently operate on large (or even infinite) Enumerable collections.
|
61
|
+
|
62
|
+
Lazy combination of Enumerables
|
63
|
+
-------------------------------
|
64
|
+
|
65
|
+
EnumerableFu also provides some interesting ways to combine several Enumerable collections to create a new collection. Again, these operate "lazily".
|
66
|
+
|
67
|
+
`EnumerableFu.zipping` pulls elements from a number of collections in parallel, yielding each group.
|
34
68
|
|
35
69
|
array1 = [1,3,6]
|
36
70
|
array2 = [2,4,7]
|
37
|
-
|
71
|
+
EnumerableFu.zipping(array1, array2) # generates: [1,2], [3,4], [6,7]
|
38
72
|
|
39
|
-
`
|
73
|
+
`EnumerableFu.merging` merges multiple collections, preserving sort-order. The inputs are assumed to be sorted already.
|
40
74
|
|
41
75
|
array1 = [1,4,5]
|
42
76
|
array2 = [2,3,6]
|
43
|
-
|
77
|
+
EnumerableFu.merging(array1, array2) # generates: 1, 2, 3, 4, 5, 6
|
44
78
|
|
45
|
-
Variant `
|
79
|
+
Variant `EnumerableFu.merging_by` uses a block to determine sort-order.
|
46
80
|
|
47
81
|
array1 = %w(a dd cccc)
|
48
82
|
array2 = %w(eee bbbbb)
|
49
|
-
|
83
|
+
EnumerableFu.merging_by(array1, array2) { |x| x.length }
|
50
84
|
# generates: %w(a dd eee cccc bbbbb)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe EnumerableFu, :needs_enumerators => true do
|
4
4
|
|
5
5
|
describe ".merging" do
|
6
6
|
|
@@ -8,14 +8,14 @@ describe Enumerable, :needs_enumerators => true do
|
|
8
8
|
@array1 = [1,3,6]
|
9
9
|
@array2 = [2,4,7]
|
10
10
|
@array3 = [5,8]
|
11
|
-
@merge =
|
11
|
+
@merge = EnumerableFu.merging(@array1, @array2, @array3)
|
12
12
|
@merge.to_a.should == [1,2,3,4,5,6,7,8]
|
13
13
|
end
|
14
14
|
|
15
15
|
it "is lazy" do
|
16
16
|
@enum1 = [1,3]
|
17
17
|
@enum2 = [2,4].with_time_bomb
|
18
|
-
@merge =
|
18
|
+
@merge = EnumerableFu.merging(@enum1, @enum2)
|
19
19
|
@merge.take(4).should == [1,2,3,4]
|
20
20
|
end
|
21
21
|
|
@@ -26,7 +26,7 @@ describe Enumerable, :needs_enumerators => true do
|
|
26
26
|
it "uses the block to determine order" do
|
27
27
|
@array1 = %w(cccc dd a)
|
28
28
|
@array2 = %w(eeeee bbb)
|
29
|
-
@merge =
|
29
|
+
@merge = EnumerableFu.merging_by(@array1, @array2) { |s| -s.length }
|
30
30
|
@merge.to_a.should == %w(eeeee cccc bbb dd a)
|
31
31
|
end
|
32
32
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe EnumerableFu, :needs_enumerators => true do
|
4
4
|
|
5
5
|
describe "#zipping" do
|
6
6
|
|
@@ -8,12 +8,12 @@ describe Enumerable, :needs_enumerators => true do
|
|
8
8
|
@array1 = [1,3,6]
|
9
9
|
@array2 = [2,4,7]
|
10
10
|
@array3 = [5,8]
|
11
|
-
@zip =
|
11
|
+
@zip = EnumerableFu.zipping(@array1, @array2, @array3)
|
12
12
|
@zip.to_a.should == [[1,2,5], [3,4,8], [6,7,nil]]
|
13
13
|
end
|
14
14
|
|
15
15
|
it "is lazy" do
|
16
|
-
@zip =
|
16
|
+
@zip = EnumerableFu.zipping(%w(a b c), [1,2].with_time_bomb)
|
17
17
|
@zip.take(2).should == [["a", 1], ["b", 2]]
|
18
18
|
end
|
19
19
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: enumerable_fu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mike Williams
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-24 00:00:00 +10:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|