bpo-25246: Optimize deque.remove() (GH-23898)

This commit is contained in:
Raymond Hettinger 2020-12-23 11:45:06 -08:00 committed by GitHub
parent a12491681f
commit 6b1ac809b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 32 deletions

View File

@ -0,0 +1 @@
Optimized :meth:`collections.deque.remove`.

View File

@ -1128,38 +1128,6 @@ deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
PyDoc_STRVAR(insert_doc, PyDoc_STRVAR(insert_doc,
"D.insert(index, object) -- insert object before index"); "D.insert(index, object) -- insert object before index");
static PyObject *
deque_remove(dequeobject *deque, PyObject *value)
{
Py_ssize_t i, n=Py_SIZE(deque);
for (i=0 ; i<n ; i++) {
PyObject *item = deque->leftblock->data[deque->leftindex];
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
if (Py_SIZE(deque) != n) {
PyErr_SetString(PyExc_IndexError,
"deque mutated during remove().");
return NULL;
}
if (cmp > 0) {
PyObject *tgt = deque_popleft(deque, NULL);
assert (tgt != NULL);
if (_deque_rotate(deque, i))
return NULL;
Py_DECREF(tgt);
Py_RETURN_NONE;
}
else if (cmp < 0) {
_deque_rotate(deque, i);
return NULL;
}
_deque_rotate(deque, -1);
}
PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque");
return NULL;
}
PyDoc_STRVAR(remove_doc, PyDoc_STRVAR(remove_doc,
"D.remove(value) -- remove first occurrence of value."); "D.remove(value) -- remove first occurrence of value.");
@ -1227,6 +1195,48 @@ deque_del_item(dequeobject *deque, Py_ssize_t i)
return rv; return rv;
} }
static PyObject *
deque_remove(dequeobject *deque, PyObject *value)
{
PyObject *item;
block *b = deque->leftblock;
Py_ssize_t i, n = Py_SIZE(deque), index = deque->leftindex;
size_t start_state = deque->state;
int cmp, rv;
for (i = 0 ; i < n; i++) {
item = b->data[index];
Py_INCREF(item);
cmp = PyObject_RichCompareBool(item, value, Py_EQ);
Py_DECREF(item);
if (cmp < 0) {
return NULL;
}
if (start_state != deque->state) {
PyErr_SetString(PyExc_IndexError,
"deque mutated during iteration");
return NULL;
}
if (cmp > 0) {
break;
}
index++;
if (index == BLOCKLEN) {
b = b->rightlink;
index = 0;
}
}
if (i == n) {
PyErr_Format(PyExc_ValueError, "%R is not in deque", value);
return NULL;
}
rv = deque_del_item(deque, i);
if (rv == -1) {
return NULL;
}
Py_RETURN_NONE;
}
static int static int
deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
{ {