Skip to content

Commit da45d8c

Browse files
authored
🔀 Merge pull request #460 from ruby/sequence_set/min-max-with-count
✨ Add `SequenceSet#min(count)` and `#max(count)`
2 parents 14c011e + eb5dd29 commit da45d8c

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

‎lib/net/imap/sequence_set.rb

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ class IMAP
179179
# - #include_star?: Returns whether the set contains <tt>*</tt>.
180180
#
181181
# <i>Minimum and maximum value elements:</i>
182-
# - #min: Returns the minimum number in the set.
183-
# - #max: Returns the maximum number in the set.
182+
# - #min: Returns one or more minimum numbers in the set.
183+
# - #max: Returns one or more maximum numbers in the set.
184184
# - #minmax: Returns the minimum and maximum numbers in the set.
185185
#
186186
# <i>Accessing value by offset in sorted set:</i>
@@ -567,26 +567,52 @@ def disjoint?(other)
567567
empty? || input_to_tuples(other).none? { intersect_tuple? _1 }
568568
end
569569

570-
# :call-seq: max(star: :*) => integer or star or nil
570+
# :call-seq:
571+
# max(star: :*) => integer or star or nil
572+
# max(count, star: :*) => SequenceSet
571573
#
572574
# Returns the maximum value in +self+, +star+ when the set includes
573575
# <tt>*</tt>, or +nil+ when the set is empty.
574-
def max(star: :*)
575-
(val = @tuples.last&.last) && val == STAR_INT ? star : val
576+
#
577+
# When +count+ is given, a new SequenceSet is returned, containing only
578+
# the last +count+ numbers. An empty SequenceSet is returned when +self+
579+
# is empty. (+star+ is ignored when +count+ is given.)
580+
#
581+
# Related: #min, #minmax, #slice
582+
def max(count = nil, star: :*)
583+
if count
584+
slice(-[count, size].min..) || remain_frozen_empty
585+
elsif (val = @tuples.last&.last)
586+
val == STAR_INT ? star : val
587+
end
576588
end
577589

578-
# :call-seq: min(star: :*) => integer or star or nil
590+
# :call-seq:
591+
# min(star: :*) => integer or star or nil
592+
# min(count, star: :*) => SequenceSet
579593
#
580594
# Returns the minimum value in +self+, +star+ when the only value in the
581595
# set is <tt>*</tt>, or +nil+ when the set is empty.
582-
def min(star: :*)
583-
(val = @tuples.first&.first) && val == STAR_INT ? star : val
596+
#
597+
# When +count+ is given, a new SequenceSet is returned, containing only
598+
# the first +count+ numbers. An empty SequenceSet is returned when +self+
599+
# is empty. (+star+ is ignored when +count+ is given.)
600+
#
601+
# Related: #max, #minmax, #slice
602+
def min(count = nil, star: :*)
603+
if count
604+
slice(0...count) || remain_frozen_empty
605+
elsif (val = @tuples.first&.first)
606+
val != STAR_INT ? val : star
607+
end
584608
end
585609

586610
# :call-seq: minmax(star: :*) => nil or [integer, integer or star]
587611
#
588612
# Returns a 2-element array containing the minimum and maximum numbers in
589613
# +self+, or +nil+ when the set is empty.
614+
#
615+
# Related: #min, #max
590616
def minmax(star: :*); [min(star: star), max(star: star)] unless empty? end
591617

592618
# Returns false when the set is empty.
@@ -1276,6 +1302,7 @@ def slice_range(range)
12761302
# Net::IMAP::SequenceSet["500:*"].limit(max: 37)
12771303
# #=> Net::IMAP::SequenceSet["37"]
12781304
#
1305+
# Related: #limit!
12791306
def limit(max:)
12801307
max = to_tuple_int(max)
12811308
if empty? then self.class.empty

‎test/net/imap/test_sequence_set.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ def compare_to_reference_set(nums, set, seqset)
8282
end
8383
end
8484

85+
data "#min(count)", {transform: ->{ _1.min(10) }, }
86+
data "#max(count)", {transform: ->{ _1.max(10) }, }
8587
data "#slice(length)", {transform: ->{ _1.slice(0, 10) }, }
8688
data "#slice(range)", {transform: ->{ _1.slice(0...10) }, }
8789
data "#slice => empty", {transform: ->{ _1.slice(0...0) }, }
@@ -580,6 +582,11 @@ def obj.to_sequence_set; 192_168.001_255 end
580582
assert_equal 3, SequenceSet.new("34:3").min
581583
assert_equal 345, SequenceSet.new("345,678").min
582584
assert_nil SequenceSet.new.min
585+
# with a count
586+
assert_equal SequenceSet["3:6"], SequenceSet["34:3"].min(4)
587+
assert_equal SequenceSet["345"], SequenceSet["345,678"].min(1)
588+
assert_equal SequenceSet["345,678"], SequenceSet["345,678"].min(222)
589+
assert_equal SequenceSet.empty, SequenceSet.new.min(5)
583590
end
584591

585592
test "#max" do
@@ -590,6 +597,11 @@ def obj.to_sequence_set; 192_168.001_255 end
590597
assert_equal nil, SequenceSet["345:*"].max(star: nil)
591598
assert_equal "*", SequenceSet["345:*"].max(star: "*")
592599
assert_nil SequenceSet.new.max(star: "ignored")
600+
# with a count
601+
assert_equal SequenceSet["31:34"], SequenceSet["34:3"].max(4)
602+
assert_equal SequenceSet["678"], SequenceSet["345,678"].max(1)
603+
assert_equal SequenceSet["345,678"], SequenceSet["345,678"].max(222)
604+
assert_equal SequenceSet.empty, SequenceSet.new.max(5)
593605
end
594606

595607
test "#minmax" do

0 commit comments

Comments
 (0)