diff options
author | Raymond Hettinger <python@rcn.com> | 2007-11-08 02:52:43 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2007-11-08 02:52:43 (GMT) |
commit | 1760c8a017ca87dc3b21d383542a23bca4370b34 (patch) | |
tree | 8bd8d6076cba0e0135ef83f46467353fcd3a50f2 | |
parent | 004c1c15621eff6bda20c66ce4e5d5c49c90ff25 (diff) | |
download | cpython-1760c8a017ca87dc3b21d383542a23bca4370b34.zip cpython-1760c8a017ca87dc3b21d383542a23bca4370b34.tar.gz cpython-1760c8a017ca87dc3b21d383542a23bca4370b34.tar.bz2 |
Add set.isdisjoint()
-rw-r--r-- | Doc/library/stdtypes.rst | 7 | ||||
-rw-r--r-- | Lib/test/test_set.py | 49 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Objects/setobject.c | 70 |
4 files changed, 126 insertions, 2 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index a74758b..f394b23 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1467,6 +1467,13 @@ operations: Test *x* for non-membership in *s*. +.. method:: set.isdisjoint(other) + + Return True if the set has no elements in common with *other*. + Sets are disjoint if and only if their interesection is the empty set. + + .. versionadded:: 2.6 + .. method:: set.issubset(other) set <= other diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 872a467..aba046a 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -102,6 +102,20 @@ class TestJointOps(unittest.TestCase): self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc')) self.assertEqual(self.thetype('abcba').intersection(C('ef')), set('')) + def test_isdisjoint(self): + def f(s1, s2): + 'Pure python equivalent of isdisjoint()' + return not set(s1).intersection(s2) + for larg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef': + s1 = self.thetype(larg) + for rarg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef': + for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple: + s2 = C(rarg) + actual = s1.isdisjoint(s2) + expected = f(s1, s2) + self.assertEqual(actual, expected) + self.assert_(actual is True or actual is False) + def test_and(self): i = self.s.intersection(self.otherword) self.assertEqual(self.s & set(self.otherword), i) @@ -657,6 +671,18 @@ class TestBasicOps(unittest.TestCase): result = empty_set & self.set self.assertEqual(result, empty_set) + def test_self_isdisjoint(self): + result = self.set.isdisjoint(self.set) + self.assertEqual(result, not self.set) + + def test_empty_isdisjoint(self): + result = self.set.isdisjoint(empty_set) + self.assertEqual(result, True) + + def test_isdisjoint_empty(self): + result = empty_set.isdisjoint(self.set) + self.assertEqual(result, True) + def test_self_symmetric_difference(self): result = self.set ^ self.set self.assertEqual(result, empty_set) @@ -835,6 +861,22 @@ class TestBinaryOps(unittest.TestCase): result = self.set & set([8]) self.assertEqual(result, empty_set) + def test_isdisjoint_subset(self): + result = self.set.isdisjoint(set((2, 4))) + self.assertEqual(result, False) + + def test_isdisjoint_superset(self): + result = self.set.isdisjoint(set([2, 4, 6, 8])) + self.assertEqual(result, False) + + def test_isdisjoint_overlap(self): + result = self.set.isdisjoint(set([3, 4, 5])) + self.assertEqual(result, False) + + def test_isdisjoint_non_overlap(self): + result = self.set.isdisjoint(set([8])) + self.assertEqual(result, True) + def test_sym_difference_subset(self): result = self.set ^ set((2, 4)) self.assertEqual(result, set([6])) @@ -1456,11 +1498,14 @@ class TestVariousIteratorArgs(unittest.TestCase): def test_inline_methods(self): s = set('november') for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'): - for meth in (s.union, s.intersection, s.difference, s.symmetric_difference): + for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint): for g in (G, I, Ig, L, R): expected = meth(data) actual = meth(G(data)) - self.assertEqual(sorted(actual), sorted(expected)) + if isinstance(expected, bool): + self.assertEqual(actual, expected) + else: + self.assertEqual(sorted(actual), sorted(expected)) self.assertRaises(TypeError, meth, X(s)) self.assertRaises(TypeError, meth, N(s)) self.assertRaises(ZeroDivisionError, meth, E(s)) @@ -12,6 +12,8 @@ What's New in Python 2.6 alpha 1? Core and builtins ----------------- +- sets and frozensets now have an isdisjoint() method. + - optimize the performance of builtin.sum(). - Fix warnings found by the new version of the Coverity checker. diff --git a/Objects/setobject.c b/Objects/setobject.c index 025a79b..140d945 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1332,6 +1332,72 @@ set_iand(PySetObject *so, PyObject *other) return (PyObject *)so; } +static PyObject * +set_isdisjoint(PySetObject *so, PyObject *other) +{ + PyObject *key, *it, *tmp; + + if ((PyObject *)so == other) { + if (PySet_GET_SIZE(so) == 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; + } + + if (PyAnySet_CheckExact(other)) { + Py_ssize_t pos = 0; + setentry *entry; + + if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { + tmp = (PyObject *)so; + so = (PySetObject *)other; + other = tmp; + } + while (set_next((PySetObject *)other, &pos, &entry)) { + int rv = set_contains_entry(so, entry); + if (rv == -1) + return NULL; + if (rv) + Py_RETURN_FALSE; + } + Py_RETURN_TRUE; + } + + it = PyObject_GetIter(other); + if (it == NULL) + return NULL; + + while ((key = PyIter_Next(it)) != NULL) { + int rv; + setentry entry; + long hash = PyObject_Hash(key); + + Py_DECREF(key); + if (hash == -1) { + Py_DECREF(it); + return NULL; + } + entry.hash = hash; + entry.key = key; + rv = set_contains_entry(so, &entry); + if (rv == -1) { + Py_DECREF(it); + return NULL; + } + if (rv) { + Py_DECREF(it); + Py_RETURN_FALSE; + } + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_TRUE; +} + +PyDoc_STRVAR(isdisjoint_doc, +"Return True if two sets have a null intersection."); + static int set_difference_update_internal(PySetObject *so, PyObject *other) { @@ -1861,6 +1927,8 @@ static PyMethodDef set_methods[] = { intersection_doc}, {"intersection_update",(PyCFunction)set_intersection_update, METH_O, intersection_update_doc}, + {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, + isdisjoint_doc}, {"issubset", (PyCFunction)set_issubset, METH_O, issubset_doc}, {"issuperset", (PyCFunction)set_issuperset, METH_O, @@ -1984,6 +2052,8 @@ static PyMethodDef frozenset_methods[] = { difference_doc}, {"intersection",(PyCFunction)set_intersection, METH_O, intersection_doc}, + {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, + isdisjoint_doc}, {"issubset", (PyCFunction)set_issubset, METH_O, issubset_doc}, {"issuperset", (PyCFunction)set_issuperset, METH_O, |