2011-10-31 27 views
24

Tengo un vector (el orden es importante) de objetos (vamos a llamarlos clase myobj) donde intento eliminar varios objetos a la vez.C++ remove_if en un vector de objetos

class vectorList 
{ 

    vector<*myobj> myList; 
}; 

class myobj 
{ 

    char* myName; 
    int index; 
    bool m_bMarkedDelete; 
} 

Estaba pensando que la mejor manera de hacer esto sería para señalar objetos específicos myObj para su eliminación y luego llamar myList.remove_if() en el vector. Sin embargo, no estoy exactamente seguro de cómo usar predicados y demás para esto. ¿Debo crear una variable miembro en el objeto que me permita decir que quiero eliminar el myobj y luego crear un predicado que compruebe si se estableció la variable miembro?

¿Cómo implemento el predicado como parte de la clase vectorList?

+1

Puede que no sea relevante, pero std :: list conserva el orden y tiene su propia función remove_if, que es mucho más rápida y no necesita el borrado por separado. – Ant

+0

@Ant: 'list :: remove_if' más rápido que eliminar y borrar en un vector? ¿Bajo que circunstancias? Eso ciertamente no ha sido el caso en muchas pruebas razonables que he hecho alguna vez. No asuma que solo porque el borrado es una operación de tiempo constante para la lista, será más rápido. La contigüidad y las garantías de acceso aleatorio de 'std :: vector' lo compran muchísimo. –

Respuesta

34

¿Debo crear una variable miembro en el objeto que me permite decir que quiero borrar el myObj y luego crear un predicado que comprobaciones para ver si se establece la variable de miembro?

¿No has hecho eso ya? ¿No es eso para lo que es m_bMarkedDelete? Se podría escribir el predicado como esto:

bool IsMarkedToDelete(const myobj & o) 
{ 
    return o.m_bMarkedDelete; 
} 

continuación:

myList.erase(
    std::remove_if(myList.begin(), myList.end(), IsMarkedToDelete), 
    myList.end()); 

O, usando lambdas:

myList.erase(
    std::remove_if(myList.begin(), myList.end(), 
     [](const myobj & o) { return o.m_bMarkedDelete; }), 
    myList.end()); 

Si la clase no tiene realmente ese miembro, y que' preguntando si debería, entonces yo diría que no. ¿Qué criterios usó para decidir marcarlo para su eliminación? Utilizar ese mismo criterio en su predicado, por ejemplo:

bool IndexGreaterThanTen(const myobj & o) 
{ 
    return o.index > 10; 
} 

nota - Las funciones que he escrito son, por supuesto, no es válida ya que todos sus miembros son privadas. Entonces necesitarás alguna forma de acceder a ellos.

+0

Aparece el siguiente error porque es un puntero: error C2662: 'myobj :: IsMarkedToDelete': no ​​se puede convertir 'este' puntero de 'const myobj' a 'myobj &. Lo estoy marcando para su eliminación, ya que lo hago desde una clase que tiene una cuadrícula que está sincronizada con mi vector. Tengo que eliminar las filas en la grilla y luego eliminar las filas seleccionadas correspondientes en el vector. – Jordan

+0

@Jordan: No debería ser miembro, debería ser una función gratuita. –

+0

¿IsMarkedToDelete debe ser una función gratuita? Parece que el problema es con la "const-ness" del objeto ... – Jordan

8

Un predicado es básicamente una comparación condicional. Puede ser una función u objeto. Aquí hay un ejemplo usando nuevas lambdas C++. Este código pasará por el vector y quitar los valores iguales a 3.

int arg[6] = {1, 2, 3, 3, 3, 5}; 
std::vector<int> vec(arg, arg+6); 
vec.erase(
    std::remove_if(
     vec.begin(), vec.end(), 
     [](int i){ return i == 3;}), 
    vec.end()); 

Editar: Para los perros que vamos a decir que tenía un vector o interfaces que podría ponerlos a nullptr luego eliminarlos en un lote con bastante más o menos el mismo código En VS2008 no tendrá lambdas, entonces haga una función de predicado de comparación o struct en su lugar.

bool ShouldDelete(IAbstractBase* i) 
{ 
    return i == nullptr; 
    // you can put whatever you want here like: 
    // return i->m_bMarkedDelete; 
} 

std::vector<IAbstractBase*> vec; 
vec.erase(
    std::remove_if(
     vec.begin(), vec.end(), 
     ShouldDelete), 
    vec.end()); 
+0

¿Cómo haré eso si el vector es una lista de punteros myobj *? Esa es una de las cosas que me confunden. ¿Y esto funcionará en VS 2008? ¡Gracias! – Jordan