Skip to content

Commit cf54642

Browse files
committed
✨ Add SequenceSet#min(count) and #max(count)
When `count` is given to either of these methods, a new `SequenceSet` is returned, containing only the last `count` numbers. An empty SequenceSet is returned when `self` is empty. The goal is for these to behave similarly to `Array#min`/`#max` when they are given a count.
1 parent a017176 commit cf54642

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

lib/net/imap/sequence_set.rb

Lines changed: 30 additions & 10 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,24 +567,44 @@ 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.
574576
#
575-
# Related: #min, #minmax
576-
def max(star: :*)
577-
(val = @tuples.last&.last) && val == STAR_INT ? star : val
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
578588
end
579589

580-
# :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
581593
#
582594
# Returns the minimum value in +self+, +star+ when the only value in the
583595
# set is <tt>*</tt>, or +nil+ when the set is empty.
584-
def min(star: :*)
585-
(val = @tuples.first&.first) && val == STAR_INT ? star : val
586596
#
587-
# Related: #max, #minmax
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
588608
end
589609

590610
# :call-seq: minmax(star: :*) => nil or [integer, integer or star]

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)