Skip to content

Commit f7c6559

Browse files
committed
[vector] Supported list/tuple indexing in vector slicing
1 parent ec4350b commit f7c6559

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

include/eigenpy/std-vector.hpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ struct overload_base_get_item_for_std_vector
8686
template <class Class>
8787
void visit(Class &cl) const {
8888
cl.def("__getitem__", &base_get_item_int)
89-
.def("__getitem__", &base_get_item_slice);
89+
.def("__getitem__", &base_get_item_slice)
90+
.def("__getitem__", &base_get_item_list)
91+
.def("__getitem__", &base_get_item_tuple);
9092
}
9193

9294
private:
@@ -131,6 +133,54 @@ struct overload_base_get_item_for_std_vector
131133
return out;
132134
}
133135

136+
static bp::object base_get_item_list(bp::back_reference<Container&> c, bp::list idxs) {
137+
const Py_ssize_t m = bp::len(idxs);
138+
bp::list out;
139+
for (Py_ssize_t k = 0; k < m; ++k) {
140+
bp::object obj = idxs[k];
141+
bp::extract<long> ei(obj);
142+
if (!ei.check()) {
143+
PyErr_SetString(PyExc_TypeError, "indices must be integers");
144+
bp::throw_error_already_set();
145+
}
146+
auto idx = normalize_index(c.get().size(), ei());
147+
out.append(elem_ref(c.get(), idx));
148+
}
149+
return out;
150+
}
151+
152+
static bp::object base_get_item_tuple(bp::back_reference<Container&> c, bp::tuple idxs) {
153+
const Py_ssize_t m = bp::len(idxs);
154+
bp::list out;
155+
for (Py_ssize_t k = 0; k < m; ++k) {
156+
bp::object obj = idxs[k];
157+
bp::extract<long> ei(obj);
158+
if (!ei.check()) {
159+
PyErr_SetString(PyExc_TypeError, "indices must be integers");
160+
bp::throw_error_already_set();
161+
}
162+
auto idx = normalize_index(c.get().size(), ei());
163+
out.append(elem_ref(c.get(), idx));
164+
}
165+
return out;
166+
}
167+
168+
static index_type normalize_index(std::size_t n, long i) {
169+
long idx = i;
170+
if (idx < 0) idx += static_cast<long>(n);
171+
if (idx < 0 || idx >= static_cast<long>(n)) {
172+
PyErr_SetString(PyExc_IndexError, "index out of range");
173+
bp::throw_error_already_set();
174+
}
175+
return static_cast<index_type>(idx);
176+
}
177+
178+
static bp::object elem_ref(Container& c, index_type i) {
179+
typename bp::to_python_indirect<value_type&,
180+
bp::detail::make_reference_holder> conv;
181+
return bp::object(bp::handle<>(conv(c[i])));
182+
}
183+
134184
static index_type convert_index(Container &container, PyObject *i_) {
135185
bp::extract<long> i(i_);
136186
if (i.check()) {

unittest/python/test_std_vector.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,11 @@ def checkZero(v):
107107
checkAllValues(l6[1:], l6.tolist()[1:])
108108
checkAllValues(l6[:-1], l6.tolist()[:-1])
109109
checkAllValues(l6[::2], l6.tolist()[::2])
110+
L = [0, 2]
111+
L6_copy = l6[L]
112+
for k, i in enumerate(L):
113+
checkAllValues(L6_copy[k], l6[i])
114+
T = (0, 2)
115+
L6_copy = l6[T]
116+
for k, i in enumerate(L):
117+
checkAllValues(L6_copy[k], l6[i])

0 commit comments

Comments
 (0)