2

From Cython I'm using C++'s std:vector and I need to remove an element. For my exact use case all of the vectors are of type int. I thought that the cleanest way to do this would be to use std:remove and vector's erase method. For some reason the following code is not removing the elements as expected:

# distutils: language=c++
from libcpp.vector cimport vector
cdef extern from "<algorithm>" namespace "std":
     iter std_remove "std::remove" [iter, T](iter first, iter last, const T& val)

cdef void remove(vector[int] vect, int elem):
    vect.erase(std_remove[vector[int].iterator, int](vect.begin(), vect.end(), elem))

def blah():
    cdef vector[int] vect
    cdef int i
    for i in range(10):
        vect.push_back(i)
    for i in range(10):
        print vect[i]
        remove(vect, i)
    return vect

When I run print blah() I see:

0
1
...
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In other words the elements are not being removed from the vector. What simple mistake am I making?

Ben Mabey
  • 1,269
  • 10
  • 18
  • For starters, it is spelled `std::remove`. Second, your `remove` declaration is different between your first and second code blocks - which definition are you actually using? – nneonneo Jun 19 '15 at 17:16
  • Sorry @nneonneo, I updated my code. I found the issues with the declaration (the `::` being one of them) but now the remove doesn't seem to be working as expected. The question now reflects that. – Ben Mabey Jun 19 '15 at 17:22
  • To answer your other question @nneonneo, I have defined a `std_remove` which gets called by my `remove` function that is suppose to actually `erase` the element from the vector. – Ben Mabey Jun 19 '15 at 17:24
  • When you modify `vect` in your `remove()` function, are you operating on a *reference* to `vect`, or are you operating on a *copy* of `vect`? If you want a *reference*, see [this link](http://stackoverflow.com/a/21721727/478288). – chrisaycock Jun 19 '15 at 17:29
  • Thanks @chrisaycock, I just figured out that is what I was missing. – Ben Mabey Jun 19 '15 at 17:33
  • @BenMabey So you accepted an "answer" that didn't address your issue? – chrisaycock Jun 19 '15 at 17:34

1 Answers1

3

Removing an element from a vector in C++ is extremely easy. Your erase/remove combo is for more complicated stuff.

Given an iterator it, then

v.erase(it)

will erase it (see the pertinent vector doc).


Incidentally, if you need to find this iterator, you can use find (from algorithm):

std::find(v.begin(), v.end(), value);

Consequently, to erase the first occurrence of value, you can use

v.erase(std::find(v.begin(), v.end(), value));

P.S. This isn't really a Cython question at all. It's a C++ question which came up in the context of Cython. Please consider retagging. This will help you get attention for your question from relevant people.

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • 1
    Okay, thanks for pointing out `find` and the erase/remove idiom. I was able to update my code to use find but the elements are still not being removed: https://gist.github.com/bmabey/6b2ea582fd4c8a463af9 – Ben Mabey Jun 19 '15 at 17:27
  • Nevermind, I was missing a `&` of course. :) Thanks again. – Ben Mabey Jun 19 '15 at 17:32