facets 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +2 -0
- data/README +58 -140
- data/demo/bench/enumerable/bench_collect.rb +84 -0
- data/demo/bench/enumerable/bench_count.rb +58 -0
- data/demo/bench/{bench_factorial.rb → integer/bench_factorial.rb} +0 -0
- data/lib/core/facets/enumerable.rb +0 -1
- data/lib/core/facets/enumerable/collect.rb +152 -61
- data/lib/core/facets/enumerable/count.rb +12 -14
- data/lib/core/facets/integer/of.rb +8 -3
- data/lib/methods/facets/enumerable/cluster_by.rb +1 -1
- data/lib/methods/facets/enumerable/collect_if.rb +1 -1
- data/lib/methods/facets/enumerable/divide.rb +1 -1
- data/lib/methods/facets/enumerable/each_by.rb +1 -1
- data/lib/methods/facets/enumerable/each_pair.rb +1 -1
- data/lib/methods/facets/enumerable/eachn.rb +1 -1
- data/lib/methods/facets/enumerable/group_by.rb +1 -0
- data/lib/methods/facets/enumerable/map_if.rb +1 -1
- data/lib/methods/facets/enumerable/partition_by.rb +1 -1
- data/meta/manifest.txt +6 -3
- data/meta/version.txt +1 -1
- data/task/clean +2 -2
- data/task/groups +1 -0
- data/task/methods +7 -3
- data/task/rdoc.yaml +1 -0
- data/task/test +4 -2
- data/test/unit/enumerable/test_collect.rb +161 -38
- metadata +10 -8
- data/lib/core/facets/enumerable/partition.rb +0 -285
- data/test/unit/enumerable/test_partition.rb +0 -134
data/AUTHORS
CHANGED
@@ -49,6 +49,7 @@ work is greatly appreciated.
|
|
49
49
|
* Tim Pease
|
50
50
|
* Jonas Pfenniger
|
51
51
|
* Ryan Platte
|
52
|
+
* Oliver Renaud
|
52
53
|
* Christoph Rippel
|
53
54
|
* Daniel Schierbeck
|
54
55
|
* Gavin Sinclair
|
@@ -57,6 +58,7 @@ work is greatly appreciated.
|
|
57
58
|
* Peter Vanbroekhoven
|
58
59
|
* Jim Weirich
|
59
60
|
* Jeff Wood
|
61
|
+
* Erik Veenstra
|
60
62
|
* Austin Ziegler
|
61
63
|
* Why The Lucky Stiff
|
62
64
|
|
data/README
CHANGED
@@ -7,68 +7,54 @@
|
|
7
7
|
|
8
8
|
== Introduction
|
9
9
|
|
10
|
-
Ruby Facets is the
|
11
|
-
and system additions for the Ruby programming language.
|
10
|
+
Ruby Facets is the single largest collection of general purpose method extensions and system additions for the Ruby programming language.
|
12
11
|
|
13
|
-
The core extensions is a large collection of methods which extend the core capabilities of Ruby's
|
14
|
-
built-in classes and modules. This collection of extension methods are unique by virtue of
|
15
|
-
their atomicity. The methods are stored in relatively small groups of tightly coupled methods so
|
16
|
-
that each can be required independently. This gives developers the potential for much finer
|
17
|
-
control over which extra methods to bring into their code.
|
12
|
+
The core extensions is a large collection of methods which extend the core capabilities of Ruby's built-in classes and modules. This collection of extension methods are unique by virtue of their atomicity. The methods are stored in relatively small groups of tightly coupled methods so that each can be required independently. This gives developers the potential for much finer control over which extra methods to bring into their code.
|
18
13
|
|
19
|
-
The "more" additions are a collection of classes, modules and light meta-systems which
|
20
|
-
consitutes an ever improving source of reusable components. Some very nice additions are
|
21
|
-
provided, from the simple Functor class to a full-blown annotations system.
|
14
|
+
The "more" additions are a collection of classes, modules and light meta-systems which constitutes an ever improving source of reusable components. Some very nice additions are provided, from the simple Functor class to a full-blown annotations system.
|
22
15
|
|
23
16
|
|
24
17
|
== Installation
|
25
18
|
|
26
|
-
|
19
|
+
The easiest way to install is via RubyGems.
|
27
20
|
|
28
|
-
|
21
|
+
$ gem install facets
|
29
22
|
|
30
|
-
|
23
|
+
To install manually, download and unpack the .tar.gz package and use the included
|
24
|
+
task/install script. Eg.
|
31
25
|
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
$ tar -xvzf facets-2.x.x.tar.gz
|
27
|
+
$ cd facets-2.x.x
|
28
|
+
$ sudo task/setup
|
35
29
|
|
30
|
+
On Window the last step will be:
|
36
31
|
|
37
|
-
|
32
|
+
C:\> ruby task/setup
|
38
33
|
|
39
|
-
|
40
|
-
classes and modules, respectively. With 2.0, the idea of CORE has take only a
|
41
|
-
slightly new meaning. Instead CORE now represents the libraries that are considerd essential
|
42
|
-
and as such are loaded automatically when using ++require "facets"++. While still primarily
|
43
|
-
made up of extension methods a few classes now belong to core as well. In conjuction
|
44
|
-
with this the extension methods are no longer stored on a per-method basis, but rather in
|
45
|
-
tight knit packs. While dividing the extension methods up on a per-method basis had certain advantages,
|
46
|
-
not the least of which was a simple organization, it proved too granular --rather than "atomic"
|
47
|
-
it was "subatomic". With 2.0 we have address this issue. All the extension methods have now been
|
48
|
-
orgnized into small tightly related groups.
|
34
|
+
IMPORTANT! Note that setup.rb is no longer used b/c of Facets' new layout.
|
49
35
|
|
50
|
-
However, being able to require on the basis of a method is still a useful approach,
|
51
|
-
so a compatability layer for the 1.x series has been created. It makes it possible to
|
52
|
-
load Facets libraries on a per method basis, just as before, via require redirection.
|
53
36
|
|
54
|
-
|
37
|
+
== Compatibility with 1.x series.
|
38
|
+
|
39
|
+
Prior to 2.0, Facets was divided between CORE and MORE --standalone extensions vs. classes and modules, respectively. With 2.0, the notion of "CORE" has taken only a slightly differnt meaning. Instead CORE now consists of the libraries that are thought essential and as such are loaded automatically when using ++require "facets"++. While still primarily made up of extension methods a few classes now belong to core as well.
|
40
|
+
|
41
|
+
Additionally, the extension methods are no longer stored on a per-method basis. While dividing the extension methods up on a per-method basis had certain advantages, not the least of which was a simple organization, it proved too granular --more "subatomic" than "atomic". With 2.0 we have address this issue. All the extension methods have now been organized into small tightly related groups.
|
42
|
+
However, being able to require on the basis of a method is still a useful approach, so a compatibility layer for the 1.x series has been created. It makes it possible to load Facets libraries on a per method basis, just as before, via require redirection. For example:
|
55
43
|
|
56
|
-
require 'facets/
|
44
|
+
require 'facets/string/underscore'
|
57
45
|
|
58
|
-
Will redirect according to the content of the underscore.rb file:
|
46
|
+
Will redirect according to the content of the underscore.rb file which is:
|
59
47
|
|
60
48
|
require 'facets/string/stylize'
|
61
49
|
|
62
|
-
So the underscore method will be loaded just as before. But a few other *stylization*
|
63
|
-
|
64
|
-
|
50
|
+
So the underscore method will be loaded just as before. But a few other *stylization* methods will also be loaded. This actually proves a more useful approach because quite often a related method is needed as well.
|
51
|
+
|
52
|
+
The other significant change from 1.x to 2.0 is the removal of some libraries that were considered too extraneous for a general purpose library. Most of these were spun-off to their own projects. In particular, the web-related libs are now part of Blow (http://blow.rubyforge.org), inflection libraries are in English (http://english.rubyforge.org), units.rb along with constants.rb are in Stick (http://stick.rubyforge.org), and the persistance system in Opod (http://opod.rubyforge.org).
|
65
53
|
|
66
54
|
|
67
55
|
== Mission
|
68
56
|
|
69
|
-
Facets holds to the notion that the more we can reasonably integrate into
|
70
|
-
a common foundation directed toward general needs, the better that foundation
|
71
|
-
will be able to serve everyone. There are a number of advantages here:
|
57
|
+
Facets holds to the notion that the more we can reasonably integrate into a common foundation directed toward general needs, the better that foundation will be able to serve everyone. There are a number of advantages here:
|
72
58
|
|
73
59
|
* Better Code-reuse
|
74
60
|
* Collaborative Improvements
|
@@ -78,43 +64,24 @@ will be able to serve everyone. There are a number of advantages here:
|
|
78
64
|
|
79
65
|
== Status
|
80
66
|
|
81
|
-
The current status is
|
82
|
-
beta, everything is relatively usable.
|
83
|
-
|
67
|
+
The current status of Facets is very good. While some libs could still use some "finishing" work, all are highly API stable and functional.
|
84
68
|
|
85
|
-
== Installation
|
86
|
-
|
87
|
-
The easiest way to install is via RubyGems. On the command line enter:
|
88
|
-
|
89
|
-
> gem install facets
|
90
|
-
|
91
|
-
To manually install, unpack the .tar.bz2 package and use the included
|
92
|
-
setup.rb script. For example:
|
93
|
-
|
94
|
-
> tar -xvzf facets-x.x.x.tar.gz
|
95
|
-
> cd facets-x.x.x
|
96
|
-
> sudo util/setup
|
97
|
-
|
98
|
-
On Window the last step will be:
|
99
69
|
|
100
|
-
|
70
|
+
== Usage
|
101
71
|
|
72
|
+
For detailed usage of any given method or module please refer to the API RDocs.
|
102
73
|
|
103
|
-
|
74
|
+
http://facets.rubyforge.org/learn.html
|
104
75
|
|
105
|
-
|
106
|
-
API RDocs. Most are well documented. Assistance in improving
|
107
|
-
documentation though is always appreciated.
|
76
|
+
Most libraries are well documented. Assistance in improving documentation though is always appreciated.
|
108
77
|
|
109
|
-
If you plan to use more then a few of Facets core method it is recommended
|
110
|
-
that you require require the main facility.
|
78
|
+
If you plan to use more then a few of Facets core method it is recommended that you require require the main facility.
|
111
79
|
|
112
80
|
require 'facets'
|
113
81
|
|
114
82
|
This loads all the CORE functionality at once.
|
115
83
|
|
116
|
-
Of course you can use the CORE library
|
117
|
-
The general require statement for a core extensions library is:
|
84
|
+
Of course you can use the CORE library piecemeal if you prefer. The general require statement for a core extensions library is:
|
118
85
|
|
119
86
|
require 'facets/<class|module>/<method-lib>'
|
120
87
|
|
@@ -122,48 +89,38 @@ For example:
|
|
122
89
|
|
123
90
|
require 'facets/time/stamp'
|
124
91
|
|
125
|
-
Most "atoms" contain only a few methods, sometimes only one, but a few
|
126
|
-
provide quite a few method, such as ++string/indexable.rb++.
|
92
|
+
Most "atoms" contain only a few methods, sometimes only one, but a few exceptions provide quite a few method, such as ++string/indexable.rb++.
|
127
93
|
|
128
|
-
You can load per-class or per-module groups of core methods by requiring the class
|
129
|
-
or module by name. For example"
|
94
|
+
You can load per-class or per-module groups of core methods by requiring the class or module by name. For example"
|
130
95
|
|
131
96
|
require 'facets/time'
|
132
97
|
|
133
98
|
Will require all the Time method extensions.
|
134
99
|
|
135
|
-
Note that some methods that were part of CORE in 1.8 and earlier are now
|
136
|
-
part of MORE libraries. A good example is 'random.rb'. There were separated
|
137
|
-
b/c they had more specialized usecases, where as CORE extensions are
|
138
|
-
intended as general purpose.
|
100
|
+
Note that some methods that were part of CORE in 1.8 and earlier are now part of MORE libraries. A good example is 'random.rb'. There were separated b/c they had more specialized usecases, where as CORE extensions are intended as general purpose.
|
139
101
|
|
140
|
-
Using a Facets/MORE library of modules, classes or microframeworks
|
141
|
-
is essentially the same. For example:
|
102
|
+
Using a Facets/MORE library of modules, classes or microframeworks is essentially the same. For example:
|
142
103
|
|
143
104
|
require 'facets/basicobject'
|
144
105
|
|
106
|
+
Again, for details pertaining to the functionality of each feature, please see the API Docs.
|
107
|
+
|
108
|
+
|
145
109
|
# PLEASE IGNORE THIS FOR NOW
|
146
|
-
#
|
147
|
-
# It is possible to eliminate the need for the 'facets/' prefix on requires if
|
148
|
-
# the Facets libpaths are added to the LOAD_PATH. But this isn't as straight-foward
|
149
|
-
# as it is for most libraries b/c of the layout of Facets library.
|
150
|
-
#
|
151
|
-
# require 'facets-topload'
|
152
|
-
# require 'basicobject'
|
153
|
-
#
|
154
|
-
# Understand that on the off chance that another library has the same name as
|
155
|
-
# one of Facets' everything will still work fine. You will just not be able to use the
|
156
|
-
# prefixless shorcut to require it.
|
157
|
-
#
|
158
|
-
# END.
|
159
110
|
|
160
|
-
|
111
|
+
It is possible to eliminate the need for the 'facets/' prefix on requires if the Facets libpaths are added to the LOAD_PATH. But this isn't as straight-forward as it is for most libraries b/c of the layout of Facets library.
|
112
|
+
|
113
|
+
require 'facets-topload'
|
114
|
+
require 'basicobject'
|
115
|
+
|
116
|
+
Understand that on the off chance that another library has the same name as one of Facets' everything will still work fine. You will just not be able to use the prefixless shortcut to require it.
|
117
|
+
|
118
|
+
# END IGNORE.
|
161
119
|
|
162
120
|
|
163
121
|
== Method File Names
|
164
122
|
|
165
|
-
Operator method redirect files are stored using
|
166
|
-
Proc#* is 'proc/op_mul'.
|
123
|
+
Operator method redirect files are stored using English names. For instance for Proc#* is 'proc/op_mul'.
|
167
124
|
|
168
125
|
For reference, here is the chart.
|
169
126
|
|
@@ -192,43 +149,29 @@ For reference, here is the chart.
|
|
192
149
|
[]= => op_store
|
193
150
|
[] => op_fetch
|
194
151
|
|
195
|
-
Facets simply takes the '*' and translates it into a string acceptable
|
196
|
-
to all file systems. Also, if a method ends in '=', '?' or '!' it is
|
197
|
-
simply removed.
|
152
|
+
Facets simply takes the '*' and translates it into a string acceptable to all file systems. Also, if a method ends in '=', '?' or '!' it is simply removed.
|
198
153
|
|
199
154
|
|
200
155
|
== Contribute
|
201
156
|
|
202
157
|
This project thrives on contribution.
|
203
158
|
|
204
|
-
If you have any extension methods, classes, modules or small frameworks
|
205
|
-
that you think have general applicability and would like to see them
|
206
|
-
included in this project, don't hesitiate to submit. There's a very good
|
207
|
-
chance it will be included. Also, if you have better versions of any thing
|
208
|
-
already included or simply have a patch, they too are more than welcome.
|
209
|
-
We want Ruby Facets to be of the highest quality.
|
159
|
+
If you have any extension methods, classes, modules or small frameworks that you think have general applicability and would like to see them included in this project, don't hesitiate to submit. There's a very good chance it will be included. Also, if you have better versions of any thing already included or simply have a patch, they too are more than welcome. We want Ruby Facets to be of the highest quality.
|
210
160
|
|
211
161
|
|
212
162
|
== Authors
|
213
163
|
|
214
|
-
This collection was put together by, and largely written by Thomas Sawyer
|
215
|
-
(aka Trans). He can be reached via email at transfire at gmail.com.
|
164
|
+
This collection was put together by, and largely written by Thomas Sawyer (aka Trans). He can be reached via email at transfire at gmail.com.
|
216
165
|
|
217
|
-
Some parts of this collection were written and/or inspired by other
|
218
|
-
persons. Fortunately nearly all were copyrighted under the same open
|
219
|
-
license, the Ruby License. In the few excpetions I have included the
|
220
|
-
copyright notice with the source code.
|
166
|
+
Some parts of this collection were written and/or inspired by other persons. Fortunately nearly all were copyrighted under the same open license, the Ruby License. In the few exceptions I have included the copyright notice with the source code.
|
221
167
|
|
222
|
-
Any code file not specifically
|
168
|
+
Any code file not specifically labeled shall fall under the Ruby License.
|
223
169
|
|
224
|
-
In all cases, I have made every effort to give credit where credit is due.
|
225
|
-
You will find these copyrights, thanks and acknowledgements embedded in the
|
226
|
-
source code, and an unobtrusive "Author(s)" section is given in the RDocs.
|
170
|
+
In all cases, I have made every effort to give credit where credit is due. You will find these copyrights, thanks and acknowledgments embedded in the source code, and an unobtrusive "Author(s)" section is given in the RDocs.
|
227
171
|
|
228
172
|
Also see the AUTHORS file for a list of all contributing Rubyists.
|
229
173
|
|
230
|
-
If anyone is missing from the list, please let me know and
|
231
|
-
I will correct right away. Thanks.
|
174
|
+
If anyone is missing from the list, please let me know and I will correct right away. Thanks.
|
232
175
|
|
233
176
|
|
234
177
|
== License
|
@@ -240,27 +183,9 @@ The collection PER COLLECTION is licensed as follows:
|
|
240
183
|
|
241
184
|
Distributed under the terms of the Ruby license.
|
242
185
|
|
243
|
-
The Ruby license is a dual license that also provides for use of the GPL.
|
244
|
-
Complete texts of both licenses accompany this document (see doc/COPYING).
|
245
|
-
|
246
|
-
This program is free software; you can redistribute it and/or modify
|
247
|
-
it under the terms of the GNU General Public License as published by
|
248
|
-
the Free Software Foundation; either version 2 of the License, or
|
249
|
-
(at your option) any later version.
|
250
|
-
|
251
|
-
This program is distributed in the hope that it will be useful,
|
252
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
253
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
254
|
-
GNU General Public License for more details.
|
255
|
-
|
256
|
-
You should have received a copy of the GNU General Public License
|
257
|
-
along with this program; if not, write to the Free Software
|
258
|
-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
186
|
+
The Ruby license is a dual license that also provides for use of the GPL. Complete texts of both licenses accompany this document (see LICENSE).
|
259
187
|
|
260
|
-
Acknowledgments and Copyrights for particular snippets of borrowed code
|
261
|
-
are given in their respective source. All licenses are either compatible
|
262
|
-
with the Ruby license (namely the GPL) or the original author has given
|
263
|
-
permission for inclusion of their code under such lincense.
|
188
|
+
Acknowledgments and Copyrights for particular snippets of borrowed code are given in their respective source. All licenses are either compatible with the Ruby license (namely the GPL) or the original author has given permission for inclusion of their code under such license.
|
264
189
|
|
265
190
|
|
266
191
|
== Pitch
|
@@ -270,14 +195,7 @@ permission for inclusion of their code under such lincense.
|
|
270
195
|
|
271
196
|
----
|
272
197
|
|
273
|
-
[1] A lot of mental anguish went into finding this good project name Ruby Facets.
|
274
|
-
Of course, in the end only one name can take the honor. Other good names
|
275
|
-
which were considered: Calibre, Florida and California, Warchest w/ Atomix,
|
276
|
-
Downs & Ace, Trix & Atomx and even Pillbox & Pills (a _why suggestion).
|
277
|
-
Then the names that almost won out and were used for a good while:
|
278
|
-
Nano Methods and Mega Modules --great names but a little to "fad".
|
279
|
-
Finally let's not forget even older "working" titles that were used
|
280
|
-
along the way: Raspberry, ABC, Succ and the very original Tomslib.
|
198
|
+
[1] A lot of mental anguish went into finding this good project name Ruby Facets. Of course, in the end only one name can take the honor. Other good names which were considered: Calibre, Florida and California, Warchest w/ Atomix, Downs & Ace, Trix & Atomx and even Pillbox & Pills (a _why suggestion). Then the names that almost won out and were used for a good while: Nano Methods and Mega Modules --great names but a little to "fad". Finally let's not forget even older "working" titles that were used along the way: Raspberry, ABC, Succ and the very original Tomslib.
|
281
199
|
|
282
200
|
----
|
283
201
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
module Enumerable
|
4
|
+
|
5
|
+
# group_by
|
6
|
+
|
7
|
+
def group_by_1(&block)
|
8
|
+
h = k = e = nil
|
9
|
+
r = Hash.new
|
10
|
+
each{|e| (r[yield(e)] ||= []) << e}
|
11
|
+
r
|
12
|
+
end
|
13
|
+
|
14
|
+
def group_by_2(&block)
|
15
|
+
r = Hash.new{ |h,k| h[k]=[] }
|
16
|
+
each{|e| r[yield(e)] << e}
|
17
|
+
r
|
18
|
+
end
|
19
|
+
|
20
|
+
# cluster_by
|
21
|
+
|
22
|
+
def cluster_by_1(&block)
|
23
|
+
group_by_1(&block).values # No sorting.
|
24
|
+
end
|
25
|
+
|
26
|
+
def cluster_by_2(&block)
|
27
|
+
#partition_by_fast(&block).values.sort # Sorted by value.
|
28
|
+
group_by_1(&block).sort.transpose.pop # Sorted by key.
|
29
|
+
end
|
30
|
+
|
31
|
+
def cluster_by_3(&block) # As defined by Facets.
|
32
|
+
h = {}
|
33
|
+
each{|e| (h[block[e]] ||= []) << e}
|
34
|
+
h.keys.sort!.map{|k| h[k]} # Sorted by key.
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
|
41
|
+
Benchmark.bmbm do |x|
|
42
|
+
n = 10
|
43
|
+
a = (0...10000).to_a + (0...10000).to_a
|
44
|
+
h = (0...10000).inject({}){|h, e| h[e] = e ; h}
|
45
|
+
|
46
|
+
# group_by
|
47
|
+
|
48
|
+
x.report("group_by_1") do
|
49
|
+
n.times do
|
50
|
+
a.group_by_1{|e| e % 10}
|
51
|
+
h.group_by_1{|k, v| v % 10}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
x.report("group_by_2") do
|
56
|
+
n.times do
|
57
|
+
a.group_by_2{|e| e % 10}
|
58
|
+
h.group_by_2{|k, v| v % 10}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# cluster_by
|
63
|
+
|
64
|
+
x.report("cluster_by_1") do
|
65
|
+
n.times do
|
66
|
+
a.cluster_by_1{|e| e % 10}
|
67
|
+
h.cluster_by_1{|k, v| v % 10}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
x.report("cluster_by_2") do
|
72
|
+
n.times do
|
73
|
+
a.cluster_by_2{|e| e % 10}
|
74
|
+
h.cluster_by_2{|k, v| v % 10}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
x.report("cluster_by_3") do
|
79
|
+
n.times do
|
80
|
+
a.cluster_by_3{|e| e % 10}
|
81
|
+
h.cluster_by_3{|k, v| v % 10}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
module Enumerable
|
4
|
+
|
5
|
+
# duplicates
|
6
|
+
|
7
|
+
def duplicates_1
|
8
|
+
h1 = {}
|
9
|
+
h2 = {}
|
10
|
+
each {|i|
|
11
|
+
h2[i] = true if h1[i]
|
12
|
+
h1[i] = true
|
13
|
+
}
|
14
|
+
h2.keys
|
15
|
+
end
|
16
|
+
|
17
|
+
def duplicates_2
|
18
|
+
inject(Hash.new(0)){|h,v| h[v]+=1; h}.reject{|k,v| v==1}.keys
|
19
|
+
end
|
20
|
+
|
21
|
+
# uniq_by
|
22
|
+
|
23
|
+
def uniq_by_1 #:yield:
|
24
|
+
h = {}; inject([]) {|a,x| h[yield(x)] ||= a << x}
|
25
|
+
end
|
26
|
+
|
27
|
+
def uniq_by_2
|
28
|
+
inject({}) { |h,x| h[yield(x)] ||= x; h }.values
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
|
35
|
+
Benchmark.bmbm do |x|
|
36
|
+
n = 10000
|
37
|
+
a = [1,1,2,3,4,4,5,6,7,7]
|
38
|
+
|
39
|
+
# duplicates
|
40
|
+
|
41
|
+
x.report("duplicates_1") do
|
42
|
+
n.times { a.duplicates_1 }
|
43
|
+
end
|
44
|
+
|
45
|
+
x.report("duplicates_2") do
|
46
|
+
n.times { a.duplicates_2 }
|
47
|
+
end
|
48
|
+
|
49
|
+
# uniq_by
|
50
|
+
|
51
|
+
x.report("uniq_by_1") do
|
52
|
+
n.times { a.uniq_by_1{ |x| x } }
|
53
|
+
end
|
54
|
+
|
55
|
+
x.report("uniq_by_2") do
|
56
|
+
n.times { a.uniq_by_2{ |x| x } }
|
57
|
+
end
|
58
|
+
end
|