rubysl-set 1.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -5
- data/lib/rubysl/set.rb +1 -1
- data/lib/rubysl/set/set.rb +313 -201
- data/lib/rubysl/set/version.rb +1 -1
- data/rubysl-set.gemspec +0 -1
- metadata +3 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c403dcc5fa5dfafb5beac4923ffde24d14dda17
|
4
|
+
data.tar.gz: cd3319cbe7a42048b97c4b51767129557d6b138e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f3c01b3e01847a1dcefdcdf4d22db1a631c30ab8fc9e3698826e526663ab3c97995a2b56e7e4df3e496bb70123eb68cc281f005b5b60f1be9f2e15734e34ce9
|
7
|
+
data.tar.gz: 605c99022766d6f9ef1f2995529dc5372f9cf2d03560f5287c754cdd3d8715b3bde4ab4597522d9f9f7f32e59abe54c93cff50fe9aafd81305181b6ac5bf0fa3
|
data/.travis.yml
CHANGED
data/lib/rubysl/set.rb
CHANGED
data/lib/rubysl/set/set.rb
CHANGED
@@ -4,15 +4,15 @@
|
|
4
4
|
#++
|
5
5
|
# Copyright (c) 2002-2008 Akinori MUSHA <knu@iDaemons.org>
|
6
6
|
#
|
7
|
-
# Documentation by Akinori MUSHA and Gavin Sinclair.
|
7
|
+
# Documentation by Akinori MUSHA and Gavin Sinclair.
|
8
8
|
#
|
9
9
|
# All rights reserved. You can redistribute and/or modify it under the same
|
10
10
|
# terms as Ruby.
|
11
11
|
#
|
12
|
-
# $Id: set.rb
|
12
|
+
# $Id: set.rb 28095 2010-05-30 13:15:17Z marcandre $
|
13
|
+
#
|
14
|
+
# == Overview
|
13
15
|
#
|
14
|
-
# == Overview
|
15
|
-
#
|
16
16
|
# This library provides the Set class, which deals with a collection
|
17
17
|
# of unordered values with no duplicates. It is a hybrid of Array's
|
18
18
|
# intuitive inter-operation facilities and Hash's fast lookup. If you
|
@@ -20,7 +20,7 @@
|
|
20
20
|
#
|
21
21
|
# The method +to_set+ is added to Enumerable for convenience.
|
22
22
|
#
|
23
|
-
# See the Set
|
23
|
+
# See the Set and SortedSet documentation for examples of usage.
|
24
24
|
|
25
25
|
|
26
26
|
#
|
@@ -28,14 +28,13 @@
|
|
28
28
|
# This is a hybrid of Array's intuitive inter-operation facilities and
|
29
29
|
# Hash's fast lookup.
|
30
30
|
#
|
31
|
-
# Several methods accept any Enumerable object (implementing +each+)
|
32
|
-
# for greater flexibility: new, replace, merge, subtract, |, &, -, ^.
|
33
|
-
#
|
34
31
|
# The equality of each couple of elements is determined according to
|
35
32
|
# Object#eql? and Object#hash, since Set uses Hash as storage.
|
36
33
|
#
|
37
|
-
#
|
38
|
-
#
|
34
|
+
# Set is easy to use with Enumerable objects (implementing +each+).
|
35
|
+
# Most of the initializer methods and binary operators accept generic
|
36
|
+
# Enumerable objects besides sets and arrays. An Enumerable object
|
37
|
+
# can be converted to Set using the +to_set+ method.
|
39
38
|
#
|
40
39
|
# == Example
|
41
40
|
#
|
@@ -68,20 +67,49 @@ class Set
|
|
68
67
|
def initialize(enum = nil, &block) # :yields: o
|
69
68
|
@hash ||= Hash.new
|
70
69
|
|
71
|
-
|
70
|
+
enum.nil? and return
|
72
71
|
|
73
72
|
if block
|
74
|
-
enum
|
73
|
+
do_with_enum(enum) { |o| add(block[o]) }
|
75
74
|
else
|
76
75
|
merge(enum)
|
77
76
|
end
|
78
77
|
end
|
79
78
|
|
79
|
+
def do_with_enum(enum, &block)
|
80
|
+
if enum.respond_to?(:each_entry)
|
81
|
+
enum.each_entry(&block)
|
82
|
+
elsif enum.respond_to?(:each)
|
83
|
+
enum.each(&block)
|
84
|
+
else
|
85
|
+
raise ArgumentError, "value must be enumerable"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
private :do_with_enum
|
89
|
+
|
80
90
|
# Copy internal hash.
|
81
91
|
def initialize_copy(orig)
|
82
92
|
@hash = orig.instance_eval{@hash}.dup
|
83
93
|
end
|
84
94
|
|
95
|
+
def freeze # :nodoc:
|
96
|
+
super
|
97
|
+
@hash.freeze
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def taint # :nodoc:
|
102
|
+
super
|
103
|
+
@hash.taint
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def untaint # :nodoc:
|
108
|
+
super
|
109
|
+
@hash.untaint
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
85
113
|
# Returns the number of elements.
|
86
114
|
def size
|
87
115
|
@hash.size
|
@@ -105,9 +133,8 @@ class Set
|
|
105
133
|
if enum.class == self.class
|
106
134
|
@hash.replace(enum.instance_eval { @hash })
|
107
135
|
else
|
108
|
-
raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
|
109
136
|
clear
|
110
|
-
enum
|
137
|
+
merge(enum)
|
111
138
|
end
|
112
139
|
|
113
140
|
self
|
@@ -121,15 +148,15 @@ class Set
|
|
121
148
|
def flatten_merge(set, seen = Set.new)
|
122
149
|
set.each { |e|
|
123
150
|
if e.is_a?(Set)
|
124
|
-
|
125
|
-
|
126
|
-
|
151
|
+
if seen.include?(e_id = e.object_id)
|
152
|
+
raise ArgumentError, "tried to flatten recursive Set"
|
153
|
+
end
|
127
154
|
|
128
|
-
|
129
|
-
|
130
|
-
|
155
|
+
seen.add(e_id)
|
156
|
+
flatten_merge(e, seen)
|
157
|
+
seen.delete(e_id)
|
131
158
|
else
|
132
|
-
|
159
|
+
add(e)
|
133
160
|
end
|
134
161
|
}
|
135
162
|
|
@@ -161,28 +188,28 @@ class Set
|
|
161
188
|
|
162
189
|
# Returns true if the set is a superset of the given set.
|
163
190
|
def superset?(set)
|
164
|
-
raise ArgumentError, "value must be a set"
|
191
|
+
set.is_a?(Set) or raise ArgumentError, "value must be a set"
|
165
192
|
return false if size < set.size
|
166
193
|
set.all? { |o| include?(o) }
|
167
194
|
end
|
168
195
|
|
169
196
|
# Returns true if the set is a proper superset of the given set.
|
170
197
|
def proper_superset?(set)
|
171
|
-
raise ArgumentError, "value must be a set"
|
198
|
+
set.is_a?(Set) or raise ArgumentError, "value must be a set"
|
172
199
|
return false if size <= set.size
|
173
200
|
set.all? { |o| include?(o) }
|
174
201
|
end
|
175
202
|
|
176
203
|
# Returns true if the set is a subset of the given set.
|
177
204
|
def subset?(set)
|
178
|
-
raise ArgumentError, "value must be a set"
|
205
|
+
set.is_a?(Set) or raise ArgumentError, "value must be a set"
|
179
206
|
return false if set.size < size
|
180
207
|
all? { |o| set.include?(o) }
|
181
208
|
end
|
182
209
|
|
183
210
|
# Returns true if the set is a proper subset of the given set.
|
184
211
|
def proper_subset?(set)
|
185
|
-
raise ArgumentError, "value must be a set"
|
212
|
+
set.is_a?(Set) or raise ArgumentError, "value must be a set"
|
186
213
|
return false if set.size <= size
|
187
214
|
all? { |o| set.include?(o) }
|
188
215
|
end
|
@@ -191,13 +218,13 @@ class Set
|
|
191
218
|
# the element as parameter. Returns an enumerator if no block is
|
192
219
|
# given.
|
193
220
|
def each
|
194
|
-
return enum_for(
|
221
|
+
block_given? or return enum_for(__method__)
|
195
222
|
@hash.each_key { |o| yield(o) }
|
196
223
|
self
|
197
224
|
end
|
198
225
|
|
199
226
|
# Adds the given object to the set and returns self. Use +merge+ to
|
200
|
-
# add
|
227
|
+
# add many elements at once.
|
201
228
|
def add(o)
|
202
229
|
@hash[o] = true
|
203
230
|
self
|
@@ -215,7 +242,7 @@ class Set
|
|
215
242
|
end
|
216
243
|
|
217
244
|
# Deletes the given object from the set and returns self. Use +subtract+ to
|
218
|
-
# delete
|
245
|
+
# delete many items at once.
|
219
246
|
def delete(o)
|
220
247
|
@hash.delete(o)
|
221
248
|
self
|
@@ -234,12 +261,22 @@ class Set
|
|
234
261
|
# Deletes every element of the set for which block evaluates to
|
235
262
|
# true, and returns self.
|
236
263
|
def delete_if
|
264
|
+
block_given? or return enum_for(__method__)
|
237
265
|
to_a.each { |o| @hash.delete(o) if yield(o) }
|
238
266
|
self
|
239
267
|
end
|
240
268
|
|
241
|
-
#
|
269
|
+
# Deletes every element of the set for which block evaluates to
|
270
|
+
# false, and returns self.
|
271
|
+
def keep_if
|
272
|
+
block_given? or return enum_for(__method__)
|
273
|
+
to_a.each { |o| @hash.delete(o) unless yield(o) }
|
274
|
+
self
|
275
|
+
end
|
276
|
+
|
277
|
+
# Replaces the elements with ones returned by collect().
|
242
278
|
def collect!
|
279
|
+
block_given? or return enum_for(__method__)
|
243
280
|
set = self.class.new
|
244
281
|
each { |o| set << yield(o) }
|
245
282
|
replace(set)
|
@@ -249,19 +286,28 @@ class Set
|
|
249
286
|
# Equivalent to Set#delete_if, but returns nil if no changes were
|
250
287
|
# made.
|
251
288
|
def reject!
|
289
|
+
block_given? or return enum_for(__method__)
|
252
290
|
n = size
|
253
291
|
delete_if { |o| yield(o) }
|
254
292
|
size == n ? nil : self
|
255
293
|
end
|
256
294
|
|
295
|
+
# Equivalent to Set#keep_if, but returns nil if no changes were
|
296
|
+
# made.
|
297
|
+
def select!
|
298
|
+
block_given? or return enum_for(__method__)
|
299
|
+
n = size
|
300
|
+
keep_if { |o| yield(o) }
|
301
|
+
size == n ? nil : self
|
302
|
+
end
|
303
|
+
|
257
304
|
# Merges the elements of the given enumerable object to the set and
|
258
305
|
# returns self.
|
259
306
|
def merge(enum)
|
260
|
-
if enum.
|
261
|
-
@hash.update(enum.
|
307
|
+
if enum.instance_of?(self.class)
|
308
|
+
@hash.update(enum.instance_variable_get(:@hash))
|
262
309
|
else
|
263
|
-
|
264
|
-
enum.each { |o| add(o) }
|
310
|
+
do_with_enum(enum) { |o| add(o) }
|
265
311
|
end
|
266
312
|
|
267
313
|
self
|
@@ -270,43 +316,38 @@ class Set
|
|
270
316
|
# Deletes every element that appears in the given enumerable object
|
271
317
|
# and returns self.
|
272
318
|
def subtract(enum)
|
273
|
-
|
274
|
-
enum.each { |o| delete(o) }
|
319
|
+
do_with_enum(enum) { |o| delete(o) }
|
275
320
|
self
|
276
321
|
end
|
277
322
|
|
278
323
|
# Returns a new set built by merging the set and the elements of the
|
279
324
|
# given enumerable object.
|
280
325
|
def |(enum)
|
281
|
-
raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
|
282
326
|
dup.merge(enum)
|
283
327
|
end
|
284
|
-
alias + |
|
285
|
-
alias union |
|
328
|
+
alias + | ##
|
329
|
+
alias union | ##
|
286
330
|
|
287
331
|
# Returns a new set built by duplicating the set, removing every
|
288
332
|
# element that appears in the given enumerable object.
|
289
333
|
def -(enum)
|
290
|
-
raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
|
291
334
|
dup.subtract(enum)
|
292
335
|
end
|
293
|
-
alias difference -
|
336
|
+
alias difference - ##
|
294
337
|
|
295
338
|
# Returns a new set containing elements common to the set and the
|
296
339
|
# given enumerable object.
|
297
340
|
def &(enum)
|
298
|
-
raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
|
299
341
|
n = self.class.new
|
300
|
-
enum
|
342
|
+
do_with_enum(enum) { |o| n.add(o) if include?(o) }
|
301
343
|
n
|
302
344
|
end
|
303
|
-
alias intersection &
|
345
|
+
alias intersection & ##
|
304
346
|
|
305
347
|
# Returns a new set containing elements exclusive between the set
|
306
348
|
# and the given enumerable object. (set ^ enum) is equivalent to
|
307
349
|
# ((set | enum) - (set & enum)).
|
308
350
|
def ^(enum)
|
309
|
-
raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
|
310
351
|
n = Set.new(enum)
|
311
352
|
each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
|
312
353
|
n
|
@@ -314,20 +355,23 @@ class Set
|
|
314
355
|
|
315
356
|
# Returns true if two sets are equal. The equality of each couple
|
316
357
|
# of elements is defined according to Object#eql?.
|
317
|
-
def ==(
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
358
|
+
def ==(other)
|
359
|
+
if self.equal?(other)
|
360
|
+
true
|
361
|
+
elsif other.instance_of?(self.class)
|
362
|
+
@hash == other.instance_variable_get(:@hash)
|
363
|
+
elsif other.is_a?(Set) && self.size == other.size
|
364
|
+
other.all? { |o| @hash.include?(o) }
|
365
|
+
else
|
366
|
+
false
|
367
|
+
end
|
324
368
|
end
|
325
369
|
|
326
|
-
def hash
|
370
|
+
def hash # :nodoc:
|
327
371
|
@hash.hash
|
328
372
|
end
|
329
373
|
|
330
|
-
def eql?(o)
|
374
|
+
def eql?(o) # :nodoc:
|
331
375
|
return false unless o.is_a?(Set)
|
332
376
|
@hash.eql?(o.instance_eval{@hash})
|
333
377
|
end
|
@@ -346,6 +390,8 @@ class Set
|
|
346
390
|
# # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
|
347
391
|
# # 2002=>#<Set: {"f.rb"}>}
|
348
392
|
def classify # :yields: o
|
393
|
+
block_given? or return enum_for(__method__)
|
394
|
+
|
349
395
|
h = {}
|
350
396
|
|
351
397
|
each { |i|
|
@@ -373,26 +419,28 @@ class Set
|
|
373
419
|
# # #<Set: {3, 4}>,
|
374
420
|
# # #<Set: {6}>}>
|
375
421
|
def divide(&func)
|
422
|
+
func or return enum_for(__method__)
|
423
|
+
|
376
424
|
if func.arity == 2
|
377
425
|
require 'tsort'
|
378
426
|
|
379
|
-
class << dig = {}
|
380
|
-
|
427
|
+
class << dig = {} # :nodoc:
|
428
|
+
include TSort
|
381
429
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
430
|
+
alias tsort_each_node each_key
|
431
|
+
def tsort_each_child(node, &block)
|
432
|
+
fetch(node).each(&block)
|
433
|
+
end
|
386
434
|
end
|
387
435
|
|
388
436
|
each { |u|
|
389
|
-
|
390
|
-
|
437
|
+
dig[u] = a = []
|
438
|
+
each{ |v| func.call(u, v) and a << v }
|
391
439
|
}
|
392
440
|
|
393
441
|
set = Set.new()
|
394
442
|
dig.each_strongly_connected_component { |css|
|
395
|
-
|
443
|
+
set.add(self.class.new(css))
|
396
444
|
}
|
397
445
|
set
|
398
446
|
else
|
@@ -419,88 +467,153 @@ class Set
|
|
419
467
|
end
|
420
468
|
end
|
421
469
|
|
422
|
-
def pretty_print(pp)
|
470
|
+
def pretty_print(pp) # :nodoc:
|
423
471
|
pp.text sprintf('#<%s: {', self.class.name)
|
424
472
|
pp.nest(1) {
|
425
473
|
pp.seplist(self) { |o|
|
426
|
-
|
474
|
+
pp.pp o
|
427
475
|
}
|
428
476
|
}
|
429
477
|
pp.text "}>"
|
430
478
|
end
|
431
479
|
|
432
|
-
def pretty_print_cycle(pp)
|
480
|
+
def pretty_print_cycle(pp) # :nodoc:
|
433
481
|
pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
|
434
482
|
end
|
435
483
|
end
|
436
484
|
|
437
|
-
#
|
485
|
+
#
|
486
|
+
# SortedSet implements a Set that guarantees that it's element are
|
487
|
+
# yielded in sorted order (according to the return values of their
|
488
|
+
# #<=> methods) when iterating over them.
|
489
|
+
#
|
490
|
+
# All elements that are added to a SortedSet must respond to the <=>
|
491
|
+
# method for comparison.
|
492
|
+
#
|
493
|
+
# Also, all elements must be <em>mutually comparable</em>: <tt>el1 <=>
|
494
|
+
# el2</tt> must not return <tt>nil</tt> for any elements <tt>el1</tt>
|
495
|
+
# and <tt>el2</tt>, else an ArgumentError will be raised when
|
496
|
+
# iterating over the SortedSet.
|
497
|
+
#
|
498
|
+
# == Example
|
499
|
+
#
|
500
|
+
# require "set"
|
501
|
+
#
|
502
|
+
# set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3])
|
503
|
+
# ary = []
|
504
|
+
#
|
505
|
+
# set.each do |obj|
|
506
|
+
# ary << obj
|
507
|
+
# end
|
508
|
+
#
|
509
|
+
# p ary # => [1, 2, 3, 4, 5, 6]
|
510
|
+
#
|
511
|
+
# set2 = SortedSet.new([1, 2, "3"])
|
512
|
+
# set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed
|
513
|
+
#
|
438
514
|
class SortedSet < Set
|
439
515
|
@@setup = false
|
440
516
|
|
441
517
|
class << self
|
442
|
-
def [](*ary)
|
518
|
+
def [](*ary) # :nodoc:
|
443
519
|
new(ary)
|
444
520
|
end
|
445
|
-
end
|
446
|
-
|
447
|
-
def initialize(*args, &block)
|
448
|
-
@keys = nil
|
449
|
-
super
|
450
|
-
end
|
451
|
-
|
452
|
-
def clear
|
453
|
-
@keys = nil
|
454
|
-
super
|
455
|
-
end
|
456
|
-
|
457
|
-
def replace(enum)
|
458
|
-
@keys = nil
|
459
|
-
super
|
460
|
-
end
|
461
521
|
|
462
|
-
|
463
|
-
|
464
|
-
@keys = nil
|
465
|
-
@hash[o] = true
|
466
|
-
self
|
467
|
-
end
|
468
|
-
|
469
|
-
alias << add
|
522
|
+
def setup # :nodoc:
|
523
|
+
@@setup and return
|
470
524
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
525
|
+
module_eval {
|
526
|
+
# a hack to shut up warning
|
527
|
+
alias old_init initialize
|
528
|
+
remove_method :old_init
|
529
|
+
}
|
530
|
+
begin
|
531
|
+
require 'rbtree'
|
532
|
+
|
533
|
+
module_eval %{
|
534
|
+
def initialize(*args, &block)
|
535
|
+
@hash = RBTree.new
|
536
|
+
super
|
537
|
+
end
|
538
|
+
|
539
|
+
def add(o)
|
540
|
+
o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
|
541
|
+
super
|
542
|
+
end
|
543
|
+
alias << add
|
544
|
+
}
|
545
|
+
rescue LoadError
|
546
|
+
module_eval %{
|
547
|
+
def initialize(*args, &block)
|
548
|
+
@keys = nil
|
549
|
+
super
|
550
|
+
end
|
551
|
+
|
552
|
+
def clear
|
553
|
+
@keys = nil
|
554
|
+
super
|
555
|
+
end
|
556
|
+
|
557
|
+
def replace(enum)
|
558
|
+
@keys = nil
|
559
|
+
super
|
560
|
+
end
|
561
|
+
|
562
|
+
def add(o)
|
563
|
+
o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
|
564
|
+
@keys = nil
|
565
|
+
super
|
566
|
+
end
|
567
|
+
alias << add
|
568
|
+
|
569
|
+
def delete(o)
|
570
|
+
@keys = nil
|
571
|
+
@hash.delete(o)
|
572
|
+
self
|
573
|
+
end
|
574
|
+
|
575
|
+
def delete_if
|
576
|
+
block_given? or return enum_for(__method__)
|
577
|
+
n = @hash.size
|
578
|
+
super
|
579
|
+
@keys = nil if @hash.size != n
|
580
|
+
self
|
581
|
+
end
|
582
|
+
|
583
|
+
def keep_if
|
584
|
+
block_given? or return enum_for(__method__)
|
585
|
+
n = @hash.size
|
586
|
+
super
|
587
|
+
@keys = nil if @hash.size != n
|
588
|
+
self
|
589
|
+
end
|
590
|
+
|
591
|
+
def merge(enum)
|
592
|
+
@keys = nil
|
593
|
+
super
|
594
|
+
end
|
595
|
+
|
596
|
+
def each
|
597
|
+
block_given? or return enum_for(__method__)
|
598
|
+
to_a.each { |o| yield(o) }
|
599
|
+
self
|
600
|
+
end
|
601
|
+
|
602
|
+
def to_a
|
603
|
+
(@keys = @hash.keys).sort! unless @keys
|
604
|
+
@keys
|
605
|
+
end
|
606
|
+
}
|
607
|
+
end
|
494
608
|
|
495
|
-
|
496
|
-
unless @keys
|
497
|
-
keys = @hash.keys
|
498
|
-
keys.sort!
|
499
|
-
@keys = keys
|
609
|
+
@@setup = true
|
500
610
|
end
|
501
|
-
@keys
|
502
611
|
end
|
503
612
|
|
613
|
+
def initialize(*args, &block) # :nodoc:
|
614
|
+
SortedSet.setup
|
615
|
+
initialize(*args, &block)
|
616
|
+
end
|
504
617
|
end
|
505
618
|
|
506
619
|
module Enumerable
|
@@ -515,97 +628,97 @@ end
|
|
515
628
|
# == RestricedSet class
|
516
629
|
# RestricedSet implements a set with restrictions defined by a given
|
517
630
|
# block.
|
518
|
-
#
|
631
|
+
#
|
519
632
|
# === Super class
|
520
633
|
# Set
|
521
|
-
#
|
634
|
+
#
|
522
635
|
# === Class Methods
|
523
636
|
# --- RestricedSet::new(enum = nil) { |o| ... }
|
524
637
|
# --- RestricedSet::new(enum = nil) { |rset, o| ... }
|
525
638
|
# Creates a new restricted set containing the elements of the given
|
526
639
|
# enumerable object. Restrictions are defined by the given block.
|
527
|
-
#
|
640
|
+
#
|
528
641
|
# If the block's arity is 2, it is called with the RestrictedSet
|
529
642
|
# itself and an object to see if the object is allowed to be put in
|
530
643
|
# the set.
|
531
|
-
#
|
644
|
+
#
|
532
645
|
# Otherwise, the block is called with an object to see if the object
|
533
646
|
# is allowed to be put in the set.
|
534
|
-
#
|
647
|
+
#
|
535
648
|
# === Instance Methods
|
536
649
|
# --- restriction_proc
|
537
650
|
# Returns the restriction procedure of the set.
|
538
|
-
#
|
651
|
+
#
|
539
652
|
# =end
|
540
|
-
#
|
653
|
+
#
|
541
654
|
# class RestricedSet < Set
|
542
655
|
# def initialize(*args, &block)
|
543
656
|
# @proc = block or raise ArgumentError, "missing a block"
|
544
|
-
#
|
657
|
+
#
|
545
658
|
# if @proc.arity == 2
|
546
659
|
# instance_eval %{
|
547
|
-
#
|
548
|
-
#
|
549
|
-
#
|
550
|
-
#
|
551
|
-
#
|
552
|
-
#
|
553
|
-
#
|
554
|
-
#
|
555
|
-
#
|
556
|
-
#
|
557
|
-
#
|
558
|
-
#
|
559
|
-
#
|
560
|
-
#
|
561
|
-
#
|
562
|
-
#
|
563
|
-
#
|
564
|
-
#
|
565
|
-
#
|
566
|
-
#
|
567
|
-
#
|
568
|
-
#
|
569
|
-
#
|
570
|
-
#
|
571
|
-
#
|
572
|
-
#
|
573
|
-
#
|
574
|
-
#
|
575
|
-
#
|
660
|
+
# def add(o)
|
661
|
+
# @hash[o] = true if @proc.call(self, o)
|
662
|
+
# self
|
663
|
+
# end
|
664
|
+
# alias << add
|
665
|
+
#
|
666
|
+
# def add?(o)
|
667
|
+
# if include?(o) || !@proc.call(self, o)
|
668
|
+
# nil
|
669
|
+
# else
|
670
|
+
# @hash[o] = true
|
671
|
+
# self
|
672
|
+
# end
|
673
|
+
# end
|
674
|
+
#
|
675
|
+
# def replace(enum)
|
676
|
+
# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
|
677
|
+
# clear
|
678
|
+
# enum.each_entry { |o| add(o) }
|
679
|
+
#
|
680
|
+
# self
|
681
|
+
# end
|
682
|
+
#
|
683
|
+
# def merge(enum)
|
684
|
+
# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
|
685
|
+
# enum.each_entry { |o| add(o) }
|
686
|
+
#
|
687
|
+
# self
|
688
|
+
# end
|
576
689
|
# }
|
577
690
|
# else
|
578
691
|
# instance_eval %{
|
579
|
-
#
|
692
|
+
# def add(o)
|
580
693
|
# if @proc.call(o)
|
581
|
-
#
|
582
|
-
# end
|
583
|
-
# self
|
584
|
-
# end
|
585
|
-
# alias << add
|
586
|
-
#
|
587
|
-
# def add?(o)
|
588
|
-
# if include?(o) || !@proc.call(o)
|
589
|
-
# nil
|
590
|
-
# else
|
591
|
-
# @hash[o] = true
|
592
|
-
# self
|
593
|
-
# end
|
694
|
+
# @hash[o] = true
|
594
695
|
# end
|
696
|
+
# self
|
697
|
+
# end
|
698
|
+
# alias << add
|
699
|
+
#
|
700
|
+
# def add?(o)
|
701
|
+
# if include?(o) || !@proc.call(o)
|
702
|
+
# nil
|
703
|
+
# else
|
704
|
+
# @hash[o] = true
|
705
|
+
# self
|
706
|
+
# end
|
707
|
+
# end
|
595
708
|
# }
|
596
709
|
# end
|
597
|
-
#
|
710
|
+
#
|
598
711
|
# super(*args)
|
599
712
|
# end
|
600
|
-
#
|
713
|
+
#
|
601
714
|
# def restriction_proc
|
602
715
|
# @proc
|
603
716
|
# end
|
604
717
|
# end
|
605
718
|
|
606
|
-
|
607
|
-
|
608
|
-
|
719
|
+
if $0 == __FILE__
|
720
|
+
eval DATA.read, nil, $0, __LINE__+4
|
721
|
+
end
|
609
722
|
|
610
723
|
__END__
|
611
724
|
|
@@ -635,7 +748,6 @@ class TC_Set < Test::Unit::TestCase
|
|
635
748
|
Set.new([])
|
636
749
|
Set.new([1,2])
|
637
750
|
Set.new('a'..'c')
|
638
|
-
Set.new('XYZ')
|
639
751
|
}
|
640
752
|
assert_raises(ArgumentError) {
|
641
753
|
Set.new(false)
|
@@ -723,12 +835,12 @@ class TC_Set < Test::Unit::TestCase
|
|
723
835
|
set1 = Set[
|
724
836
|
1,
|
725
837
|
Set[
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
838
|
+
5,
|
839
|
+
Set[7,
|
840
|
+
Set[0]
|
841
|
+
],
|
842
|
+
Set[6,2],
|
843
|
+
1
|
732
844
|
],
|
733
845
|
3,
|
734
846
|
Set[3,4]
|
@@ -904,14 +1016,14 @@ class TC_Set < Test::Unit::TestCase
|
|
904
1016
|
assert_same(set, ret)
|
905
1017
|
|
906
1018
|
e = set.each
|
907
|
-
assert_instance_of(
|
1019
|
+
assert_instance_of(Enumerator, e)
|
908
1020
|
|
909
1021
|
assert_nothing_raised {
|
910
1022
|
set.each { |o|
|
911
|
-
|
1023
|
+
ary.delete(o) or raise "unexpected element: #{o}"
|
912
1024
|
}
|
913
1025
|
|
914
|
-
raise "forgotten elements: #{ary.join(', ')}"
|
1026
|
+
ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
|
915
1027
|
}
|
916
1028
|
end
|
917
1029
|
|
@@ -973,11 +1085,11 @@ class TC_Set < Test::Unit::TestCase
|
|
973
1085
|
ret = set.collect! { |i|
|
974
1086
|
case i
|
975
1087
|
when Numeric
|
976
|
-
|
1088
|
+
i * 2
|
977
1089
|
when String
|
978
|
-
|
1090
|
+
i.upcase
|
979
1091
|
else
|
980
|
-
|
1092
|
+
nil
|
981
1093
|
end
|
982
1094
|
}
|
983
1095
|
|
@@ -1102,15 +1214,15 @@ class TC_Set < Test::Unit::TestCase
|
|
1102
1214
|
assert_equal(set, ret.flatten)
|
1103
1215
|
ret.each { |s|
|
1104
1216
|
if s.include?(0)
|
1105
|
-
|
1217
|
+
assert_equal(Set[0,1], s)
|
1106
1218
|
elsif s.include?(3)
|
1107
|
-
|
1219
|
+
assert_equal(Set[3,4,5], s)
|
1108
1220
|
elsif s.include?(7)
|
1109
|
-
|
1221
|
+
assert_equal(Set[7], s)
|
1110
1222
|
elsif s.include?(9)
|
1111
|
-
|
1223
|
+
assert_equal(Set[9,10,11], s)
|
1112
1224
|
else
|
1113
|
-
|
1225
|
+
raise "unexpected group: #{s.inspect}"
|
1114
1226
|
end
|
1115
1227
|
}
|
1116
1228
|
end
|
@@ -1204,33 +1316,33 @@ end
|
|
1204
1316
|
# class TC_RestricedSet < Test::Unit::TestCase
|
1205
1317
|
# def test_s_new
|
1206
1318
|
# assert_raises(ArgumentError) { RestricedSet.new }
|
1207
|
-
#
|
1319
|
+
#
|
1208
1320
|
# s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
|
1209
1321
|
# assert_equal([2,3], s.sort)
|
1210
1322
|
# end
|
1211
|
-
#
|
1323
|
+
#
|
1212
1324
|
# def test_restriction_proc
|
1213
1325
|
# s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
|
1214
|
-
#
|
1326
|
+
#
|
1215
1327
|
# f = s.restriction_proc
|
1216
1328
|
# assert_instance_of(Proc, f)
|
1217
1329
|
# assert(f[1])
|
1218
1330
|
# assert(!f[0])
|
1219
1331
|
# end
|
1220
|
-
#
|
1332
|
+
#
|
1221
1333
|
# def test_replace
|
1222
1334
|
# s = RestricedSet.new(-3..3) { |o| o > 0 }
|
1223
1335
|
# assert_equal([1,2,3], s.sort)
|
1224
|
-
#
|
1336
|
+
#
|
1225
1337
|
# s.replace([-2,0,3,4,5])
|
1226
1338
|
# assert_equal([3,4,5], s.sort)
|
1227
1339
|
# end
|
1228
|
-
#
|
1340
|
+
#
|
1229
1341
|
# def test_merge
|
1230
1342
|
# s = RestricedSet.new { |o| o > 0 }
|
1231
1343
|
# s.merge(-5..5)
|
1232
1344
|
# assert_equal([1,2,3,4,5], s.sort)
|
1233
|
-
#
|
1345
|
+
#
|
1234
1346
|
# s.merge([10,-10,-8,8])
|
1235
1347
|
# assert_equal([1,2,3,4,5,8,10], s.sort)
|
1236
1348
|
# end
|
data/lib/rubysl/set/version.rb
CHANGED
data/rubysl-set.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubysl-set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Shirai
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.5'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rubysl-prettyprint
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.0'
|
69
55
|
description: Ruby standard library set.
|
70
56
|
email:
|
71
57
|
- brixen@gmail.com
|
@@ -205,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
191
|
version: '0'
|
206
192
|
requirements: []
|
207
193
|
rubyforge_project:
|
208
|
-
rubygems_version: 2.0.
|
194
|
+
rubygems_version: 2.0.7
|
209
195
|
signing_key:
|
210
196
|
specification_version: 4
|
211
197
|
summary: Ruby standard library set.
|