람다로 2D 벡터의 최소 요소 찾기
현재 2D 벡터의 최소 요소를 찾으려고합니다. C ++ 11 람다 함수를 사용하여 연습하려고하는데 이것이 좋은 방법이라고 생각했지만 컴파일 할 수없는 것 같습니다.
다음을 수행 할 수 있다는 것을 알고 있습니다.
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;
하지만 람다 함수로 똑같이 할 수 있는지 궁금합니다. 현재 이것이 최선의 시도입니다.
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());
});
오류가 발생합니다. 오류 C2672 : 'operator __surrogate_func': 일치하는 오버로드 된 함수가 없습니다.
작동해야한다고 생각하는 방식은 외부 min_element가 한 번에 한 행 (벡터에 대한 참조 일뿐)을 전달하여 가장 작은 값을 반환 한 다음 다른 행과 비교할 수 있다는 것입니다.
문제는 람다가 int 벡터에 대한 참조가 아닌 int 벡터에 대한 반복자를 수신하는 것일 수 있지만 역 참조가 도움이되지 않는 것 같습니다.
내가하려는 일을하는 더 좋은 방법이 있습니까?
@assembly_wizard는 min_element가 전달 된 항목 중 두 개를 비교할 수있는 조건자를 원한다고 지적했습니다. 그것은 두 줄입니다. 이로 인해 다음 코드가 생성됩니다.
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());
});
가장 작은 요소가있는 행을 찾습니다. 다른 std :: min_element로 래핑하여 작업을 수행 할 수 있지만 원격으로 도움이되는 것보다 훨씬 복잡해지고 있습니다. 누구든지 더 나은 제안이 있으면 듣고 싶습니다!
답변
주석에서 언급 한 작업을 수행하는 작업 버전을 컴파일했습니다.
#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;
}
Godbolt에서 실제로 확인하십시오.
이것은 각 행의 최소값을 개별적으로 취하므로 row_minimums
정수 벡터를 얻은 다음 모든 행 사이의 최종 결과를 얻기 위해 최소값을 취합니다.
이 코드를 for
루프 버전 보다 더 나쁘게 만드는 유일한 방법 은 row_minimums
실행하기 전에 모든 것을 한 번에 메모리에 보관한다는 min_element
것입니다. 불행히도 나는 이것을 동시에 수행하는 방법을 모르지만 STL이 기대하는 가장 큰 것은 아니므로 방법이있을 수 있습니다.
고려할 수있는 다른 옵션은 먼저 2D 행렬을 1D 벡터로 연결 한 다음이를 사용 min_element
하거나 편집에 포함 된 옵션을 min_element
3 번 호출하는 것 입니다.
또한 이 SO 답변 에는 boost
라이브러리를 사용하는 솔루션에 관한 흥미로운 정보가있는 것 같습니다 .하지만 그것이 무엇인지 정확히 모르겠습니다.
좀 더 간단합니다. std :: for_each를 사용하면 행렬의 각 벡터를 반복하고 최소 요소를 얻습니다. min
참조로 캡처 한대로 모두의 최소값을 얻습니다.
#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;
}