Skip to content

Commit 1fc7a52

Browse files
authored
πŸ”€ Merge pull request #549 from ruby/sequence_set/intersect-bang
✨ Add `SequenceSet#intersect!` for in-place set `AND`
2 parents dd7ecd7 + b648645 commit 1fc7a52

File tree

4 files changed

+40
-17
lines changed

4 files changed

+40
-17
lines changed

β€Žbenchmarks/sequence_set-and.ymlβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ prelude: |
6565
6666
benchmark:
6767
" L & R": l, r = sets; l & r
68+
"mut! L & R": l, r = sets; l.intersect! r
6869
" L - ~R": l, r = sets; l - ~r
6970
"and0 L - ~R": l, r = sets; l.and0 r
7071
"and0! L - ~R": l, r = sets; l.and0! r

β€Žbenchmarks/sequence_set-xor.ymlβ€Ž

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ prelude: |
3131
merge(other).subtract(other.subtract(copy.complement!))
3232
end
3333
34-
# TODO: add this as a public method
3534
def intersect!(other) # :nodoc:
3635
modifying!
3736
subtract SequenceSet.new(other).complement!
38-
end
37+
end unless instance_methods.include?(:intersect!)
3938
4039
# (L | R) - (L & R)
4140
def xor2!(other)

β€Žlib/net/imap/sequence_set.rbβ€Ž

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ class IMAP
332332
# given maximum value and removed all members over that maximum.
333333
#
334334
# === Methods for Assigning
335-
# These methods add or replace elements in +self+.
335+
# These methods add or replace numbers in +self+.
336336
#
337337
# <i>Normalized (sorted and coalesced):</i>
338338
#
@@ -341,8 +341,10 @@ class IMAP
341341
# - #add (aliased as #<<): Adds a given element to the set; returns +self+.
342342
# - #add?: If the given element is not fully included the set, adds it and
343343
# returns +self+; otherwise, returns +nil+.
344-
# - #merge: Adds all members of the given sets into this set; returns +self+.
345-
# - #complement!: Replaces the contents of the set with its own #complement.
344+
# - #merge: In-place set #union. Adds all members of the given sets into
345+
# this set; returns +self+.
346+
# - #complement!: In-place set #complement. Replaces the contents of this
347+
# set with its own #complement; returns +self+.
346348
#
347349
# <i>Order preserving:</i>
348350
#
@@ -355,18 +357,20 @@ class IMAP
355357
# of a given object.
356358
#
357359
# === Methods for Deleting
358-
# These methods remove elements from +self+, and update #string to be fully
360+
# These methods remove numbers from +self+, and update #string to be fully
359361
# sorted and coalesced.
360362
#
361363
# - #clear: Removes all elements in the set; returns +self+.
362364
# - #delete: Removes a given element from the set; returns +self+.
363365
# - #delete?: If the given element is included in the set, removes it and
364366
# returns it; otherwise, returns +nil+.
365367
# - #delete_at: Removes the number at a given offset.
368+
# - #intersect!: In-place set #intersection. Removes numbers that are not
369+
# in the given set; returns +self+.
366370
# - #slice!: Removes the number or consecutive numbers at a given offset or
367371
# range of offsets.
368-
# - #subtract: Removes all members of the given sets from this set; returns
369-
# +self+.
372+
# - #subtract: In-place set #difference. Removes all members of the given
373+
# sets from this set; returns +self+.
370374
# - #limit!: Replaces <tt>*</tt> with a given maximum value and removes all
371375
# members over that maximum; returns +self+.
372376
#
@@ -873,9 +877,7 @@ def -(other) remain_frozen dup.subtract other end
873877
# * <tt>lhs - (lhs - rhs)</tt>
874878
# * <tt>lhs - (lhs ^ rhs)</tt>
875879
# * <tt>lhs ^ (lhs - rhs)</tt>
876-
def &(other)
877-
remain_frozen dup.subtract SequenceSet.new(other).complement!
878-
end
880+
def &(other) remain_frozen dup.intersect! other end
879881
alias intersection :&
880882

881883
# :call-seq:
@@ -1069,8 +1071,8 @@ def slice!(index, length = nil)
10691071
deleted
10701072
end
10711073

1072-
# Merges all of the elements that appear in any of the +sets+ into the
1073-
# set, and returns +self+.
1074+
# In-place set #union. Merges all of the elements that appear in any of
1075+
# the +sets+ into this set, and returns +self+.
10741076
#
10751077
# The +sets+ may be any objects that would be accepted by ::new.
10761078
#
@@ -1083,8 +1085,8 @@ def merge(*sets)
10831085
normalize!
10841086
end
10851087

1086-
# Removes all of the elements that appear in any of the given +sets+ from
1087-
# the set, and returns +self+.
1088+
# In-place set #difference. Removes all of the elements that appear in
1089+
# any of the given +sets+ from this set, and returns +self+.
10881090
#
10891091
# The +sets+ may be any objects that would be accepted by ::new.
10901092
#
@@ -1595,8 +1597,9 @@ def limit!(max:)
15951597

15961598
# :call-seq: complement! -> self
15971599
#
1598-
# Converts the SequenceSet to its own #complement. It will contain all
1599-
# possible values _except_ for those currently in the set.
1600+
# In-place set #complement. Replaces the contents of this set with its
1601+
# own #complement. It will contain all possible values _except_ for those
1602+
# currently in the set.
16001603
#
16011604
# Related: #complement
16021605
def complement!
@@ -1610,6 +1613,22 @@ def complement!
16101613
normalize!
16111614
end
16121615

1616+
# In-place set #intersection. Removes any elements that are missing from
1617+
# +other+ from this set, keeping only the #intersection, and returns
1618+
# +self+.
1619+
#
1620+
# +other+ can be any object that would be accepted by ::new.
1621+
#
1622+
# set = Net::IMAP::SequenceSet.new(1..5)
1623+
# set.intersect! [2, 4, 6]
1624+
# set #=> Net::IMAP::SequenceSet("2,4")
1625+
#
1626+
# Related: #intersection, #intersect?
1627+
def intersect!(other)
1628+
modifying!
1629+
subtract SequenceSet.new(other).complement!
1630+
end
1631+
16131632
# Returns a new SequenceSet with a normalized string representation.
16141633
#
16151634
# The returned set's #string is sorted and deduplicated. Adjacent or

β€Žtest/net/imap/test_sequence_set.rbβ€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ def compare_to_reference_set(nums, set, seqset)
8989
assert_equal intersection, lhs - (lhs - rhs)
9090
assert_equal intersection, lhs - (lhs ^ rhs)
9191
assert_equal intersection, lhs ^ (lhs - rhs)
92+
mutable = lhs.dup
93+
assert_equal intersection, mutable.intersect!(rhs)
94+
assert_equal intersection, mutable
9295
end
9396
end
9497

@@ -168,6 +171,7 @@ def compare_to_reference_set(nums, set, seqset)
168171
data "#merge", ->{ _1.merge 1 }
169172
data "#subtract", ->{ _1.subtract 1 }
170173
data "#limit!", ->{ _1.limit! max: 10 }
174+
data "#intersect!", ->{ _1.intersect! SequenceSet[1..100] }
171175
data "#complement!", :complement!
172176
data "#normalize!", :normalize!
173177
test "frozen error message" do |modification|

0 commit comments

Comments
Β (0)