una - C++ elimina ciertos elementos del vector
insertar un elemento en un vector c++ (4)
Interpreto sus preguntas de la siguiente manera: Tiene dos vectores objPoints
y delPoints
que contienen 1000 puntos tridimensionales. Yo codificaría esto como
std::vector<std::array<int,3> > objPoints;
donde asumí que tiene un ráster tal que puede desribe sus puntos por valores int
(de lo contrario, para entradas double
, la comparación no es tan fácil).
Una de las ventajas de utilizar std::array<int,3>
es que obtiene automáticamente un orden lexicográfico de los puntos (es decir, las especializaciones de std::less
y std::equal_to
que se pueden usar directamente sin necesidad de crear algunos).
Algoritmo:
Primero ordena tus matrices. Puede haber algoritmos donde esto no es realmente necesario (ver la otra respuesta por @AshwaniDausodia), pero lo siguiente lo asume. Además, en general, al usar vectores clasificados se puede obtener un mejor rendimiento (al menos en la gran O: para contenedores sin clasificar, es aproximadamente O(size1*size2)
, mientras que es menor para el siguiente algoritmo). La clasificación primero requiere un esfuerzo de O(size1 log(size1)) + O(size2 log(size2))
A continuación, recorra ambas matrices al mismo tiempo y cada vez que encuentre un elemento común elimínelo de uno de los vectores. A medida que recorre las matrices ordenadas, donde siempre puede aumentar solo el iterador que apunta al elemento más pequeño, este paso toma O(size1+size2)
.
Implementación:
// deletes the elements from container c1 which are also present in c2
// requires sorted containers c1 and c2
//
template< class ContainerType1, class ContainerType2 >
void delete_common_elements(ContainerType1& c1, ContainerType2 const& c2 )
{
for(auto it1=c1.begin(), it2=c2.begin()
; it1!=c1.end() && it2!=c2.end(); )
{
if(*it1==*it2) // eventually change here if your points are not int''s
// but are of floating-point type
{
it1 = c1.erase(it1); //it1 is increased here
}
else
{
*it1<*it2 ? ++it1 : ++it2;
}
}
}
En conjunto, esto requiere un esfuerzo de O(c1.size()) + O(c1.size() * log(c1.size())
(asumiendo naturalmente c1.size()>=c2.size()
).
Uno puede extender esto fácilmente para tomar un operador de comparación arbitrario en lugar del operator==
.
Soy nuevo en C ++ y quiero eliminar el elemento vectorial.
Mis vectores son como:
<vector<vector>> objPoints;
<vector<vector>> delPoints;
<vector<vector>> objPoints2;
cada objPoints tiene un tamaño de 1000x3 y tiene todos los puntos. Desde objPoints quiero eliminar delPoints, es decir, los valores (X, Y, Z) que residen en cada fila.
¿Puede alguien decirme la sintaxis?
Puede considerar leer estas preguntas y respuestas en sobre cómo borrar elementos de contenedores STL .
El punto clave es usar la expresión borrar-borrar para borrar elementos del vector, y usar una lambda para expresar la condición de borrado:
objPoints.erase(
std::remove_if(
objPoints.begin(),
objPoints.end(),
[&delPoints](const Point3D& point)
{
// Erasing condition:
// Is ''point'' contained in the ''delPoints'' vector?
auto it = std::find(delPoints.begin(), delPoints.end(), point);
return (it != delPoints.end());
}),
objPoints.end());
Ejemplo completo de código compilable (en vivo aquí ):
#include <algorithm> // for std::find(), std::remove_if()
#include <array> // for std::array
#include <iostream> // for console output
#include <vector> // for std::vector
typedef std::array<int, 3> Point3D;
std::ostream& operator<<(std::ostream& os, const Point3D& point)
{
os << "{" << point[0] << ", "
<< point[1] << ", " << point[2] << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const std::vector<Point3D>& v)
{
if (v.empty())
{
os << "{ <empty> }" << std::endl;
return os;
}
os << "{/n";
for (const auto& point : v)
{
os << " " << point << ''/n'';
}
os << "}" << std::endl;
return os;
}
int main()
{
std::vector<Point3D> objPoints{{1, 2, 3},
{4, 5, 6},
{11, 22, 33},
{44, 55, 66},
{77, 88, 99}};
std::vector<Point3D> delPoints{{10, 10, 10},
{11, 22, 33},
{44, 55, 66}};
std::cout << "objPoints =/n" << objPoints << std::endl;
std::cout << "delPoints =/n" << delPoints << std::endl;
objPoints.erase(
std::remove_if(
objPoints.begin(),
objPoints.end(),
[&delPoints](const Point3D& point)
{
// Erasing condition:
// Is ''point'' contained in the ''delPoints'' vector?
auto it = std::find(delPoints.begin(), delPoints.end(), point);
return (it != delPoints.end());
}),
objPoints.end());
std::cout << "/nAfter erasing, objPoints =/n";
std::cout << objPoints << std::endl;
}
Salida:
objPoints = { {1, 2, 3} {4, 5, 6} {11, 22, 33} {44, 55, 66} {77, 88, 99} } delPoints = { {10, 10, 10} {11, 22, 33} {44, 55, 66} } After erasing, objPoints = { {1, 2, 3} {4, 5, 6} {77, 88, 99} }
Si definitivamente tiene que usar vectores, una forma fácil (pero ineficaz) sería std::find
el elemento en objPoints que desea eliminar y luego eliminarlo con std::vector::erase
.
Un método obvio sería:
for each point in delPoints
if point exists in objPoints
delete point from objPoints.
Puedes hacerlo de manera mucho más eficiente si puedes ordenar los vectores. Le proporcionaré un método y un pseudo código, luego podrá implementarlo por su cuenta.
First sort objPoints and delpoints
i=0,j=0
while i < length(objPoints) and j < length(delPoints)
if objPoints[i] > delPoints[j] // Means delPoints[j] is not there in objPoints. If it would have, we would have found it.
j++
else if objPoints[i] < delPoints[j] // Means delPoints[j] is after objPoints[i] if it is there in objPoints
i++
else
erase objPoints[i] // Means we have found delPoints[j], so delete it.
Para comaprison, primero compare wrt x cordinate
luego y
y luego z
. Para la clasificación, puede usar std::sort
con la misma función de comparación descrita en la línea anterior. Para eliminar, puede usar std::vector::erase
.
O puede implementar sus propias funciones.