Add count() method to collections.deque().

This commit is contained in:
Raymond Hettinger 2010-04-03 18:10:37 +00:00
parent 30583e3f38
commit 5f516edd77
4 changed files with 56 additions and 1 deletions

View File

@ -358,6 +358,12 @@ counts, but the output will exclude results with counts of zero or less.
Remove all elements from the deque leaving it with length 0. Remove all elements from the deque leaving it with length 0.
.. method:: count(x)
Count the number of deque elements equal to *x*.
.. versionadded:: 2.7
.. method:: extend(iterable) .. method:: extend(iterable)
Extend the right side of the deque by appending elements from the iterable Extend the right side of the deque by appending elements from the iterable

View File

@ -113,6 +113,13 @@ class TestBasic(unittest.TestCase):
d = deque('abc') d = deque('abc')
d.maxlen = 10 d.maxlen = 10
def test_count(self):
for s in ('', 'abracadabra', 'simsalabim'*500+'abc'):
s = list(s)
d = deque(s)
for letter in 'abcdefghijklmnopqrstuvwxyz':
self.assertEqual(s.count(letter), d.count(letter), (s, d, letter))
def test_comparisons(self): def test_comparisons(self):
d = deque('xabc'); d.popleft() d = deque('xabc'); d.popleft()
for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: for e in [d, deque('abc'), deque('ab'), deque(), list(d)]:

View File

@ -1223,7 +1223,7 @@ Core and Builtins
Library Library
------- -------
- Add a reverse() method to collections.deque(). - Add count() and reverse() methods to collections.deque().
- Fix variations of extending deques: d.extend(d) d.extendleft(d) d+=d - Fix variations of extending deques: d.extend(d) d.extendleft(d) d+=d

View File

@ -504,6 +504,46 @@ deque_reverse(dequeobject *deque, PyObject *unused)
PyDoc_STRVAR(reverse_doc, PyDoc_STRVAR(reverse_doc,
"D.reverse() -- reverse *IN PLACE*"); "D.reverse() -- reverse *IN PLACE*");
static PyObject *
deque_count(dequeobject *deque, PyObject *v)
{
block *leftblock = deque->leftblock;
Py_ssize_t leftindex = deque->leftindex;
Py_ssize_t n = (deque->len);
Py_ssize_t i;
Py_ssize_t count = 0;
PyObject *item;
long start_state = deque->state;
int cmp;
for (i=0 ; i<n ; i++) {
item = leftblock->data[leftindex];
cmp = PyObject_RichCompareBool(item, v, Py_EQ);
if (cmp > 0)
count++;
else if (cmp < 0)
return NULL;
if (start_state != deque->state) {
PyErr_SetString(PyExc_RuntimeError,
"deque mutated during iteration");
return NULL;
}
/* Advance left block/index pair */
leftindex++;
if (leftindex == BLOCKLEN) {
assert (leftblock->rightlink != NULL);
leftblock = leftblock->rightlink;
leftindex = 0;
}
}
return PyInt_FromSsize_t(count);
}
PyDoc_STRVAR(count_doc,
"D.count(value) -> integer -- return number of occurrences of value");
static Py_ssize_t static Py_ssize_t
deque_len(dequeobject *deque) deque_len(dequeobject *deque)
{ {
@ -991,6 +1031,8 @@ static PyMethodDef deque_methods[] = {
METH_NOARGS, clear_doc}, METH_NOARGS, clear_doc},
{"__copy__", (PyCFunction)deque_copy, {"__copy__", (PyCFunction)deque_copy,
METH_NOARGS, copy_doc}, METH_NOARGS, copy_doc},
{"count", (PyCFunction)deque_count,
METH_O, count_doc},
{"extend", (PyCFunction)deque_extend, {"extend", (PyCFunction)deque_extend,
METH_O, extend_doc}, METH_O, extend_doc},
{"extendleft", (PyCFunction)deque_extendleft, {"extendleft", (PyCFunction)deque_extendleft,