sorted_containers 0.1.1 → 1.1.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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +4 -1
- data/README.md +30 -12
- data/lib/sorted_containers/core_extensions.rb +56 -0
- data/lib/sorted_containers/sorted_array.rb +986 -209
- data/lib/sorted_containers/sorted_hash.rb +461 -53
- data/lib/sorted_containers/sorted_set.rb +310 -71
- data/lib/sorted_containers/version.rb +1 -1
- data/lib/sorted_containers.rb +1 -0
- metadata +4 -3
@@ -2,12 +2,38 @@
|
|
2
2
|
|
3
3
|
require "set"
|
4
4
|
require_relative "sorted_array"
|
5
|
+
require "forwardable"
|
5
6
|
|
6
7
|
# A module that provides sorted container data structures.
|
7
8
|
module SortedContainers
|
8
|
-
#
|
9
|
+
# rubocop:disable Metrics/ClassLength
|
10
|
+
|
11
|
+
# SortedSet is a set that maintains its elements in sorted order.
|
12
|
+
#
|
13
|
+
# SortedSet has most of the same methods as Set, but also has the following
|
14
|
+
# additional methods:
|
15
|
+
# - #bisect_left
|
16
|
+
# - #bisect_right
|
17
|
+
# - #delete_at
|
18
|
+
# - #last
|
19
|
+
# - #[]
|
20
|
+
#
|
21
|
+
# Addtionally, there are methods that work differently than their Set counterparts.
|
22
|
+
# Generally, methods that use Entry Order will use the sort order of the keys instead.
|
23
|
+
# For example:
|
24
|
+
#
|
25
|
+
# s = Set.new
|
26
|
+
# s.add(2)
|
27
|
+
# s.add(1)
|
28
|
+
# s.first # => 2
|
29
|
+
#
|
30
|
+
# ss = SortedSet.new
|
31
|
+
# ss.add(2)
|
32
|
+
# ss.add(1)
|
33
|
+
# ss.first # => 1
|
9
34
|
class SortedSet
|
10
35
|
include Enumerable
|
36
|
+
extend Forwardable
|
11
37
|
|
12
38
|
# Initializes a new instance of the SortedSet class.
|
13
39
|
#
|
@@ -15,12 +41,158 @@ module SortedContainers
|
|
15
41
|
# @param load_factor [Integer] The load factor for the sorted set.
|
16
42
|
def initialize(iterable = [], load_factor: SortedArray::DEFAULT_LOAD_FACTOR)
|
17
43
|
@set = Set.new(iterable)
|
18
|
-
@list = SortedContainers::SortedArray.new(@set
|
44
|
+
@list = SortedContainers::SortedArray.new(@set, load_factor: load_factor)
|
19
45
|
end
|
20
46
|
|
21
|
-
#
|
47
|
+
# Creates a new instance of the SortedSet class.
|
22
48
|
#
|
23
|
-
# @param
|
49
|
+
# @param args [Array] The initial elements of the sorted set.
|
50
|
+
# @return [SortedSet] A new instance of the SortedSet class.
|
51
|
+
def self.[](*args)
|
52
|
+
new(args)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @!method []
|
56
|
+
# @see SortedArray#[]
|
57
|
+
# @!method to_a
|
58
|
+
# @see SortedArray#to_a
|
59
|
+
# @!method join
|
60
|
+
# @see SortedArray#join
|
61
|
+
# @!method first
|
62
|
+
# @see SortedArray#first
|
63
|
+
# @!method last
|
64
|
+
# @see SortedArray#last
|
65
|
+
# @!method bisect_left
|
66
|
+
# @see SortedArray#bisect_left
|
67
|
+
# @!method bisect_right
|
68
|
+
# @see SortedArray#bisect_right
|
69
|
+
def_delegators :@list,
|
70
|
+
:[],
|
71
|
+
:to_a,
|
72
|
+
:join,
|
73
|
+
:first,
|
74
|
+
:last,
|
75
|
+
:bisect_left,
|
76
|
+
:bisect_right
|
77
|
+
|
78
|
+
# @!method ===
|
79
|
+
# @see Set#===
|
80
|
+
# @!method classify
|
81
|
+
# @see Set#classify
|
82
|
+
# @!method include?
|
83
|
+
# @see Set#include?
|
84
|
+
# @!method member?
|
85
|
+
# @see Set#member?
|
86
|
+
# @!method size
|
87
|
+
# @see Set#size
|
88
|
+
# @!method length
|
89
|
+
# @see Set#length
|
90
|
+
# @!method disjoint?
|
91
|
+
# @see Set#disjoint?
|
92
|
+
# @!method divide
|
93
|
+
# @see Set#divide
|
94
|
+
# @!method empty?
|
95
|
+
# @see Set#empty?
|
96
|
+
# @!method to_set
|
97
|
+
# @see Set#to_set
|
98
|
+
def_delegators :@set,
|
99
|
+
:===,
|
100
|
+
:classify,
|
101
|
+
:include?,
|
102
|
+
:member?,
|
103
|
+
:size,
|
104
|
+
:length,
|
105
|
+
:disjoint?,
|
106
|
+
:divide,
|
107
|
+
:empty?,
|
108
|
+
:to_set
|
109
|
+
|
110
|
+
# @see Set#<=>
|
111
|
+
def <=>(other)
|
112
|
+
@set <=> other.set
|
113
|
+
end
|
114
|
+
|
115
|
+
# @see Set#==
|
116
|
+
def ==(other)
|
117
|
+
@set == other.set
|
118
|
+
end
|
119
|
+
|
120
|
+
# @see Set#intersect?
|
121
|
+
def intersect?(other)
|
122
|
+
@set.intersect?(other.set)
|
123
|
+
end
|
124
|
+
|
125
|
+
# @see Set#subset?
|
126
|
+
def subset?(other)
|
127
|
+
@set.subset?(other.set)
|
128
|
+
end
|
129
|
+
alias <= subset?
|
130
|
+
|
131
|
+
# @see Set#superset?
|
132
|
+
def superset?(other)
|
133
|
+
@set.superset?(other.set)
|
134
|
+
end
|
135
|
+
alias >= superset?
|
136
|
+
|
137
|
+
# @see Set#proper_subset?
|
138
|
+
def proper_subset?(other)
|
139
|
+
@set.proper_subset?(other.set)
|
140
|
+
end
|
141
|
+
alias < proper_subset?
|
142
|
+
|
143
|
+
# @see Set#proper_superset?
|
144
|
+
def proper_superset?(other)
|
145
|
+
@set.proper_superset?(other.set)
|
146
|
+
end
|
147
|
+
alias > proper_superset?
|
148
|
+
|
149
|
+
# @see Set#intersection
|
150
|
+
def intersection(other)
|
151
|
+
SortedSet.new(@set & other.set, load_factor: @list.load_factor)
|
152
|
+
end
|
153
|
+
alias & intersection
|
154
|
+
|
155
|
+
# @see Set#union
|
156
|
+
def union(other)
|
157
|
+
SortedSet.new(@set + other.set, load_factor: @list.load_factor)
|
158
|
+
end
|
159
|
+
alias + union
|
160
|
+
alias | union
|
161
|
+
|
162
|
+
# @see Set#difference
|
163
|
+
def difference(other)
|
164
|
+
SortedSet.new(@set - other.set, load_factor: @list.load_factor)
|
165
|
+
end
|
166
|
+
alias - difference
|
167
|
+
|
168
|
+
# @see Set#^
|
169
|
+
def ^(other)
|
170
|
+
SortedSet.new(@set ^ other.set, load_factor: @list.load_factor)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Clears the sorted set. Removes all elements.
|
174
|
+
# @return [SortedSet] The sorted set.
|
175
|
+
def clear
|
176
|
+
@set.clear
|
177
|
+
@list.clear
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
# @see Set#collect!
|
182
|
+
def collect!
|
183
|
+
return enum_for(:collect!) unless block_given?
|
184
|
+
|
185
|
+
@list.collect! do |item|
|
186
|
+
new_item = yield(item)
|
187
|
+
@set.delete(item)
|
188
|
+
@set.add(new_item)
|
189
|
+
new_item
|
190
|
+
end
|
191
|
+
self
|
192
|
+
end
|
193
|
+
alias map! collect!
|
194
|
+
|
195
|
+
# @see Set#add
|
24
196
|
def add(item)
|
25
197
|
return if @set.include?(item)
|
26
198
|
|
@@ -29,42 +201,54 @@ module SortedContainers
|
|
29
201
|
end
|
30
202
|
alias << add
|
31
203
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@
|
204
|
+
# @see Set#add?
|
205
|
+
def add?(item)
|
206
|
+
return false if @set.include?(item)
|
207
|
+
|
208
|
+
@set.add(item)
|
209
|
+
@list.add(item)
|
210
|
+
self
|
37
211
|
end
|
38
212
|
|
39
213
|
# Returns a string representation of the sorted set.
|
40
214
|
#
|
41
215
|
# @return [String] A string representation of the sorted set.
|
42
216
|
def to_s
|
43
|
-
"SortedSet
|
217
|
+
"#<SortedSet: {#{to_a.join(", ")}}>"
|
44
218
|
end
|
219
|
+
alias inspect to_s
|
45
220
|
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
def first
|
50
|
-
@list.first
|
51
|
-
end
|
221
|
+
# @see Set#delete
|
222
|
+
def delete(item)
|
223
|
+
return self unless @set.include?(item)
|
52
224
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
def last
|
57
|
-
@list.last
|
225
|
+
@set.delete(item)
|
226
|
+
@list.delete(item)
|
227
|
+
self
|
58
228
|
end
|
59
229
|
|
60
|
-
#
|
61
|
-
|
62
|
-
|
63
|
-
def delete(item)
|
64
|
-
return unless @set.include?(item)
|
230
|
+
# @see Set#delete?
|
231
|
+
def delete?(item)
|
232
|
+
return unless @set.include?(item) # rubocop:disable Style/ReturnNilInPredicateMethodDefinition
|
65
233
|
|
66
234
|
@set.delete(item)
|
67
235
|
@list.delete(item)
|
236
|
+
self
|
237
|
+
end
|
238
|
+
|
239
|
+
# @see Set#delete_if
|
240
|
+
def delete_if
|
241
|
+
return enum_for(:delete_if) unless block_given?
|
242
|
+
|
243
|
+
@list.delete_if do |item|
|
244
|
+
if yield(item)
|
245
|
+
@set.delete(item)
|
246
|
+
true
|
247
|
+
else
|
248
|
+
false
|
249
|
+
end
|
250
|
+
end
|
251
|
+
self
|
68
252
|
end
|
69
253
|
|
70
254
|
# Removes the item at the specified index.
|
@@ -78,61 +262,116 @@ module SortedContainers
|
|
78
262
|
item
|
79
263
|
end
|
80
264
|
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
@list.
|
265
|
+
# @see Set#each
|
266
|
+
def each(&block)
|
267
|
+
return enum_for(:each) unless block_given?
|
268
|
+
|
269
|
+
@list.each(&block)
|
270
|
+
self
|
86
271
|
end
|
87
272
|
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
273
|
+
# @see Set#select!
|
274
|
+
def select!
|
275
|
+
return enum_for(:select!) unless block_given?
|
276
|
+
|
277
|
+
@list.filter! do |item|
|
278
|
+
if yield(item)
|
279
|
+
@set.delete(item)
|
280
|
+
true
|
281
|
+
else
|
282
|
+
false
|
283
|
+
end
|
284
|
+
end
|
285
|
+
self
|
94
286
|
end
|
287
|
+
alias filter! select!
|
95
288
|
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
# (to the left of) any existing values.
|
100
|
-
#
|
101
|
-
# Runtime complexity: `O(log(n))` -- approximate.
|
102
|
-
#
|
103
|
-
# @see SortedArray#bisect_left
|
104
|
-
# @param value [Object] The value to insert.
|
105
|
-
# @return [Integer] The index to insert the value.
|
106
|
-
def bisect_left(value)
|
107
|
-
@list.bisect_left(value)
|
289
|
+
# @see Set#flatten
|
290
|
+
def flatten(level = 1)
|
291
|
+
SortedSet.new(@list.flatten(level), load_factor: @list.load_factor)
|
108
292
|
end
|
109
293
|
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
#
|
117
|
-
# @see SortedArray#bisect_right
|
118
|
-
# @param value [Object] The value to insert.
|
119
|
-
# @return [Integer] The index to insert the value.
|
120
|
-
def bisect_right(value)
|
121
|
-
@list.bisect_right(value)
|
294
|
+
# @see Set#flatten!
|
295
|
+
def flatten!(level = 1)
|
296
|
+
@set.clear
|
297
|
+
@list.flatten!(level)
|
298
|
+
@set.merge(@list)
|
299
|
+
self
|
122
300
|
end
|
123
301
|
|
124
|
-
#
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
@list.
|
302
|
+
# @see Set#keep_if
|
303
|
+
def keep_if
|
304
|
+
return enum_for(:keep_if) unless block_given?
|
305
|
+
|
306
|
+
@list.keep_if do |item|
|
307
|
+
if yield(item)
|
308
|
+
@set.delete(item)
|
309
|
+
true
|
310
|
+
else
|
311
|
+
false
|
312
|
+
end
|
313
|
+
end
|
314
|
+
self
|
129
315
|
end
|
130
316
|
|
131
|
-
#
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
@list.
|
317
|
+
# @see Set#merge
|
318
|
+
def merge(other)
|
319
|
+
@set.merge(other.set)
|
320
|
+
@list.clear
|
321
|
+
@list.update(@set)
|
322
|
+
self
|
323
|
+
end
|
324
|
+
|
325
|
+
# rubocop:disable Metrics/MethodLength
|
326
|
+
|
327
|
+
# @see Set#reject!
|
328
|
+
def reject!
|
329
|
+
return enum_for(:reject!) unless block_given?
|
330
|
+
|
331
|
+
changed = false
|
332
|
+
@list.reject! do |item|
|
333
|
+
if yield(item)
|
334
|
+
@set.delete(item)
|
335
|
+
changed = true
|
336
|
+
true
|
337
|
+
else
|
338
|
+
false
|
339
|
+
end
|
340
|
+
end
|
341
|
+
changed ? self : nil
|
136
342
|
end
|
343
|
+
|
344
|
+
# rubocop:enable Metrics/MethodLength
|
345
|
+
|
346
|
+
# @see Set#replace
|
347
|
+
def replace(other)
|
348
|
+
@set.replace(other.set)
|
349
|
+
@list.clear
|
350
|
+
@list.update(@set)
|
351
|
+
self
|
352
|
+
end
|
353
|
+
|
354
|
+
# @see Set#reset
|
355
|
+
def reset
|
356
|
+
values = @list.to_a
|
357
|
+
@set.clear
|
358
|
+
@list.clear
|
359
|
+
@set.merge(values)
|
360
|
+
@list.update(values)
|
361
|
+
self
|
362
|
+
end
|
363
|
+
|
364
|
+
# @see Set#subtract
|
365
|
+
def subtract(other)
|
366
|
+
@set.subtract(other.set)
|
367
|
+
@list.clear
|
368
|
+
@list.update(@set)
|
369
|
+
self
|
370
|
+
end
|
371
|
+
|
372
|
+
protected
|
373
|
+
|
374
|
+
attr_reader :set, :list
|
137
375
|
end
|
376
|
+
# rubocop:enable Metrics/ClassLength
|
138
377
|
end
|
data/lib/sorted_containers.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sorted_containers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garrison Jensen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A collection of sorted containers including SortedArray, SortedDict,
|
14
14
|
and SortedSet.
|
@@ -26,6 +26,7 @@ files:
|
|
26
26
|
- README.md
|
27
27
|
- Rakefile
|
28
28
|
- lib/sorted_containers.rb
|
29
|
+
- lib/sorted_containers/core_extensions.rb
|
29
30
|
- lib/sorted_containers/sorted_array.rb
|
30
31
|
- lib/sorted_containers/sorted_hash.rb
|
31
32
|
- lib/sorted_containers/sorted_set.rb
|
@@ -55,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
56
|
- !ruby/object:Gem::Version
|
56
57
|
version: '0'
|
57
58
|
requirements: []
|
58
|
-
rubygems_version: 3.5.
|
59
|
+
rubygems_version: 3.5.16
|
59
60
|
signing_key:
|
60
61
|
specification_version: 4
|
61
62
|
summary: A collection of sorted containers including SortedArray, SortedDict, and
|