Skip to content

Commit 6b1ac80

Browse files
authored
bpo-25246: Optimize deque.remove() (GH-23898)
1 parent a124916 commit 6b1ac80

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Optimized :meth:`collections.deque.remove`.

Modules/_collectionsmodule.c

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,38 +1128,6 @@ deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
11281128
PyDoc_STRVAR(insert_doc,
11291129
"D.insert(index, object) -- insert object before index");
11301130

1131-
static PyObject *
1132-
deque_remove(dequeobject *deque, PyObject *value)
1133-
{
1134-
Py_ssize_t i, n=Py_SIZE(deque);
1135-
1136-
for (i=0 ; i<n ; i++) {
1137-
PyObject *item = deque->leftblock->data[deque->leftindex];
1138-
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
1139-
1140-
if (Py_SIZE(deque) != n) {
1141-
PyErr_SetString(PyExc_IndexError,
1142-
"deque mutated during remove().");
1143-
return NULL;
1144-
}
1145-
if (cmp > 0) {
1146-
PyObject *tgt = deque_popleft(deque, NULL);
1147-
assert (tgt != NULL);
1148-
if (_deque_rotate(deque, i))
1149-
return NULL;
1150-
Py_DECREF(tgt);
1151-
Py_RETURN_NONE;
1152-
}
1153-
else if (cmp < 0) {
1154-
_deque_rotate(deque, i);
1155-
return NULL;
1156-
}
1157-
_deque_rotate(deque, -1);
1158-
}
1159-
PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque");
1160-
return NULL;
1161-
}
1162-
11631131
PyDoc_STRVAR(remove_doc,
11641132
"D.remove(value) -- remove first occurrence of value.");
11651133

@@ -1227,6 +1195,48 @@ deque_del_item(dequeobject *deque, Py_ssize_t i)
12271195
return rv;
12281196
}
12291197

1198+
static PyObject *
1199+
deque_remove(dequeobject *deque, PyObject *value)
1200+
{
1201+
PyObject *item;
1202+
block *b = deque->leftblock;
1203+
Py_ssize_t i, n = Py_SIZE(deque), index = deque->leftindex;
1204+
size_t start_state = deque->state;
1205+
int cmp, rv;
1206+
1207+
for (i = 0 ; i < n; i++) {
1208+
item = b->data[index];
1209+
Py_INCREF(item);
1210+
cmp = PyObject_RichCompareBool(item, value, Py_EQ);
1211+
Py_DECREF(item);
1212+
if (cmp < 0) {
1213+
return NULL;
1214+
}
1215+
if (start_state != deque->state) {
1216+
PyErr_SetString(PyExc_IndexError,
1217+
"deque mutated during iteration");
1218+
return NULL;
1219+
}
1220+
if (cmp > 0) {
1221+
break;
1222+
}
1223+
index++;
1224+
if (index == BLOCKLEN) {
1225+
b = b->rightlink;
1226+
index = 0;
1227+
}
1228+
}
1229+
if (i == n) {
1230+
PyErr_Format(PyExc_ValueError, "%R is not in deque", value);
1231+
return NULL;
1232+
}
1233+
rv = deque_del_item(deque, i);
1234+
if (rv == -1) {
1235+
return NULL;
1236+
}
1237+
Py_RETURN_NONE;
1238+
}
1239+
12301240
static int
12311241
deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
12321242
{

0 commit comments

Comments
 (0)