Intentando encontrar el elemento mínimo del vector 2D con lambda
Actualmente estoy tratando de encontrar el elemento mínimo de un vector 2D. Estoy tratando de practicar el uso de funciones lambda de C ++ 11 y pensé que esto podría ser una buena práctica, pero parece que no puedo compilarlo.
Soy consciente de que podría hacer lo siguiente:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int result = std::numeric_limits<int>::max();
for(const auto& row : matrix)
{
int minElemInRow = *std::min_element(row.begin(), row.end());
result = std::min(result , minElemInRow);
}
return result;
pero me preguntaba si se podría hacer lo mismo con una función lambda. Actualmente, este es mi mejor intento:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
return *std::min_element(matrix.begin(), matrix.end(),
[](const auto& row)
{
return *std::min_element(row.begin(), row.end());
});
Recibo el error: error C2672 : 'operator __surrogate_func': no se encontró una función sobrecargada que coincida
Lo que creo que debería estar funcionando es que el min_element externo pasará en una fila a la vez (que es solo una referencia a un vector), del cual puedo devolver el más pequeño, que luego se comparará con otras filas.
Pensé que el problema podría ser que la lambda estaría recibiendo un iterador para un vector de ints en lugar de una referencia al vector de ints, pero la desreferenciación no parece ayudar.
¿Existe una mejor manera de hacer lo que estoy tratando de hacer?
@assembly_wizard señaló que min_element quiere un predicado que pueda comparar dos de los elementos que le pasaron. Eso es dos filas. Esto conduce al siguiente código:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
auto i = std::min_element(matrix.begin(), matrix.end(),
[](const auto& lhs, const auto& rhs)
{
return *std::min_element(lhs.begin(), lhs.end()) <
*std::min_element(rhs.begin(), rhs.end());
});
Esto encontrará la fila con el elemento más pequeño. Aunque puedo hacer que eso funcione envolviéndolo en otro std :: min_element, eso se está volviendo mucho más complejo que ser de ayuda remota. Si alguien tiene una sugerencia mejor, ¡me encantaría escucharla!
Respuestas
He compilado una versión funcional que hace lo que mencioné en los comentarios:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
std::vector<int> row_minimums(matrix.size());
std::transform(matrix.begin(), matrix.end(), row_minimums.begin(), [](const auto& row) {
return *std::min_element(row.begin(), row.end());
});
auto i = *std::min_element(row_minimums.begin(), row_minimums.end());
std::cout << "Minimum element is: " << i << std::endl;
}
Véalo en acción en Godbolt
Esto tomará el mínimo de cada fila por separado, por lo que obtenemos row_minimums
cuál es un vector de ints, y luego toma el mínimo de estos para obtener el resultado final entre todas las filas.
Lo único que hace que este código sea peor que la for
versión de bucle es que mantiene todo el contenido row_minimums
en la memoria a la vez, antes de ejecutarlo min_element
. Desafortunadamente, no conozco una manera de hacer esto simultáneamente, pero no soy el mejor STL esperado, así que tal vez haya una manera.
Otras opciones que podría considerar son primero concatenar la matriz 2D en un vector 1D y luego usarla min_element
, o la opción que ha incluido en su edición donde llama min_element
3 veces.
Además, esta respuesta SO parece tener información interesante sobre las soluciones que utilizan la boost
biblioteca, que podrían ser mejores, pero no estoy seguro de cuáles son exactamente.
Solo un poco más simple: con std :: for_each itera sobre cada vector en la matriz y obtiene el elemento mínimo de ellos. Como min
se captura por referencia, obtienes el mínimo de todos ellos.
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int min = std::numeric_limits<int>::max();
std::for_each(matrix.begin(), matrix.end(),
[&min](const auto& v)
{
min = std::min(*min_element(v.begin(), v.end()), min);
}
);
std::cout << "Minimum element is: " << min << std::endl;
}