[前][次][番号順一覧][スレッド一覧]

ruby-changes:63902

From: Marc-Andre <ko1@a...>
Date: Fri, 4 Dec 2020 19:44:59 +0900 (JST)
Subject: [ruby-changes:63902] 1804c3368c (master): [ruby/set] Add `Set#<=>`

https://git.ruby-lang.org/ruby.git/commit/?id=1804c3368c

From 1804c3368cf4a94791fafa9701f79a2e6f76d5d8 Mon Sep 17 00:00:00 2001
From: Marc-Andre Lafortune <github@m...>
Date: Thu, 1 Oct 2020 23:55:46 -0400
Subject: [ruby/set] Add `Set#<=>`

https://github.com/ruby/set/commit/447974a374

diff --git a/lib/set.rb b/lib/set.rb
index cb07037..625046d 100644
--- a/lib/set.rb
+++ b/lib/set.rb
@@ -45,9 +45,9 @@ https://github.com/ruby/ruby/blob/trunk/lib/set.rb#L45
 # == Comparison
 #
 # The comparison operators <, >, <=, and >= are implemented as
-# shorthand for the {proper_,}{subset?,superset?} methods.  However,
-# the <=> operator is intentionally left out because not every pair of
-# sets is comparable ({x, y} vs. {x, z} for example).
+# shorthand for the {proper_,}{subset?,superset?} methods.
+# The <=> operator reflects this order, or return `nil` for
+# sets that both have distinct elements ({x, y} vs. {x, z} for example).
 #
 # == Example
 #
@@ -302,6 +302,19 @@ class Set https://github.com/ruby/ruby/blob/trunk/lib/set.rb#L302
   end
   alias < proper_subset?
 
+  # Returns 0 if the set are equal,
+  # -1 / +1 if the set is a proper subset / superset of the given set,
+  # or nil if they both have unique elements.
+  def <=>(set)
+    return unless set.is_a?(Set)
+
+    case size <=> set.size
+    when -1 then -1 if proper_subset?(set)
+    when +1 then +1 if proper_superset?(set)
+    else 0 if self.==(set)
+    end
+  end
+
   # Returns true if the set and the given set have at least one
   # element in common.
   #
diff --git a/test/test_set.rb b/test/test_set.rb
index 54ef80b..05431e4 100644
--- a/test/test_set.rb
+++ b/test/test_set.rb
@@ -332,6 +332,24 @@ class TC_Set < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/test_set.rb#L332
     }
   end
 
+  def test_spacecraft_operator
+    set = Set[1,2,3]
+
+    assert_nil(set <=> 2)
+
+    assert_nil(set <=> set.to_a)
+
+    [Set, Set2].each { |klass|
+      assert_equal(-1,  set <=> klass[1,2,3,4], klass.name)
+      assert_equal( 0,  set <=> klass[3,2,1]  , klass.name)
+      assert_equal(nil, set <=> klass[1,2,4]  , klass.name)
+      assert_equal(+1,  set <=> klass[2,3]    , klass.name)
+      assert_equal(+1,  set <=> klass[]       , klass.name)
+
+      assert_equal(0, Set[] <=> klass[], klass.name)
+    }
+  end
+
   def assert_intersect(expected, set, other)
     case expected
     when true
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]