mirror of https://github.com/python/cpython
Generalize PySequence_Count() (operator.countOf) to work with iterators.
This commit is contained in:
parent
1434299a99
commit
75f8e35ef4
|
@ -527,4 +527,39 @@ class TestCase(unittest.TestCase):
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Test iterators with operator.countOf (PySequence_Count).
|
||||||
|
def test_countOf(self):
|
||||||
|
from operator import countOf
|
||||||
|
self.assertEqual(countOf([1,2,2,3,2,5], 2), 3)
|
||||||
|
self.assertEqual(countOf((1,2,2,3,2,5), 2), 3)
|
||||||
|
self.assertEqual(countOf("122325", "2"), 3)
|
||||||
|
self.assertEqual(countOf("122325", "6"), 0)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, countOf, 42, 1)
|
||||||
|
self.assertRaises(TypeError, countOf, countOf, countOf)
|
||||||
|
|
||||||
|
d = {"one": 3, "two": 3, "three": 3, 1j: 2j}
|
||||||
|
for k in d:
|
||||||
|
self.assertEqual(countOf(d, k), 1)
|
||||||
|
self.assertEqual(countOf(d.itervalues(), 3), 3)
|
||||||
|
self.assertEqual(countOf(d.itervalues(), 2j), 1)
|
||||||
|
self.assertEqual(countOf(d.itervalues(), 1j), 0)
|
||||||
|
|
||||||
|
f = open(TESTFN, "w")
|
||||||
|
try:
|
||||||
|
f.write("a\n" "b\n" "c\n" "b\n")
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
f = open(TESTFN, "r")
|
||||||
|
try:
|
||||||
|
for letter, count in ("a", 1), ("b", 2), ("c", 1), ("d", 0):
|
||||||
|
f.seek(0, 0)
|
||||||
|
self.assertEqual(countOf(f, letter + "\n"), count)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
try:
|
||||||
|
unlink(TESTFN)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
run_unittest(TestCase)
|
run_unittest(TestCase)
|
||||||
|
|
|
@ -23,10 +23,12 @@ Core
|
||||||
max()
|
max()
|
||||||
min()
|
min()
|
||||||
reduce()
|
reduce()
|
||||||
|
tuple() (PySequence_Tuple() and PySequence_Fast() in C API)
|
||||||
.join() method of strings
|
.join() method of strings
|
||||||
tuple()
|
'x in y' and 'x not in y' (PySequence_Contains() in C API)
|
||||||
|
operator.countOf() (PySequence_Count() in C API)
|
||||||
XXX TODO zip()
|
XXX TODO zip()
|
||||||
'x in y' and 'x not in y'
|
|
||||||
|
|
||||||
What's New in Python 2.1 (final)?
|
What's New in Python 2.1 (final)?
|
||||||
=================================
|
=================================
|
||||||
|
|
|
@ -1333,34 +1333,52 @@ PySequence_Fast(PyObject *v, const char *m)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return # of times o appears in s. */
|
||||||
int
|
int
|
||||||
PySequence_Count(PyObject *s, PyObject *o)
|
PySequence_Count(PyObject *s, PyObject *o)
|
||||||
{
|
{
|
||||||
int l, i, n, cmp, err;
|
int n; /* running count of o hits */
|
||||||
PyObject *item;
|
PyObject *it; /* iter(s) */
|
||||||
|
|
||||||
if (s == NULL || o == NULL) {
|
if (s == NULL || o == NULL) {
|
||||||
null_error();
|
null_error();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = PySequence_Size(s);
|
it = PyObject_GetIter(s);
|
||||||
if (l < 0)
|
if (it == NULL) {
|
||||||
|
type_error(".count() requires iterable argument");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
for (i = 0; i < l; i++) {
|
for (;;) {
|
||||||
item = PySequence_GetItem(s, i);
|
int cmp;
|
||||||
if (item == NULL)
|
PyObject *item = PyIter_Next(it);
|
||||||
return -1;
|
if (item == NULL) {
|
||||||
err = PyObject_Cmp(item, o, &cmp);
|
if (PyErr_Occurred())
|
||||||
|
goto Fail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmp = PyObject_RichCompareBool(o, item, Py_EQ);
|
||||||
Py_DECREF(item);
|
Py_DECREF(item);
|
||||||
if (err < 0)
|
if (cmp < 0)
|
||||||
return err;
|
goto Fail;
|
||||||
if (cmp == 0)
|
if (cmp > 0) {
|
||||||
|
if (n == INT_MAX) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"count exceeds C int size");
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
n++;
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Py_DECREF(it);
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
|
Fail:
|
||||||
|
Py_DECREF(it);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return -1 if error; 1 if v in w; 0 if v not in w. */
|
/* Return -1 if error; 1 if v in w; 0 if v not in w. */
|
||||||
|
|
Loading…
Reference in New Issue