Der Versuch, das minimale Element eines 2D-Vektors mit Lambda zu finden
Ich versuche gerade, das minimale Element eines 2D-Vektors zu finden. Ich versuche, die Verwendung von C ++ 11-Lambda-Funktionen zu üben, und habe mir gedacht, dass dies eine gute Übung sein könnte, aber es scheint nicht möglich zu sein, sie zu kompilieren.
Mir ist bewusst, dass ich Folgendes tun kann:
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;
aber ich fragte mich, ob das gleiche mit einer Lambda-Funktion gemacht werden könnte. Derzeit ist dies mein bester Versuch:
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());
});
Ich erhalte die Fehlermeldung: Fehler C2672 : 'operator __surrogate_func': Keine passende überladene Funktion gefunden
Ich denke, es sollte funktionieren, wenn das äußere min_element jeweils in einer Zeile (die nur eine Referenz auf einen Vektor ist) übergeben wird, von der ich das kleinste zurückgeben kann, das dann mit anderen Zeilen verglichen wird.
Ich dachte, das Problem könnte sein, dass das Lambda eher einen Iterator für einen Inte-Vektor als einen Verweis auf den Ints-Vektor erhält, aber eine Dereferenzierung scheint nicht zu helfen.
Gibt es einen besseren Weg, um das zu tun, was ich versuche?
@assembly_wizard wies darauf hin, dass min_element ein Prädikat möchte, das zwei der übergebenen Elemente vergleichen kann. Das sind zwei Reihen. Dies führt zu folgendem Code:
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());
});
Dadurch wird die Zeile mit dem kleinsten Element gefunden. Obwohl ich das schaffen kann, indem ich es in ein weiteres std :: min_element einpacke, wird das viel komplexer, als aus der Ferne hilfreich zu sein. Wenn jemand einen besseren Vorschlag hat, würde ich ihn gerne hören!
Antworten
Ich habe eine Arbeitsversion zusammengestellt, die das tut, was ich in den Kommentaren erwähnt habe:
#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;
}
Sehen Sie es in Aktion auf Godbolt
Dies wird das Minimum jeder Zeile separat nehmen, so dass wir row_minimums
einen Vektor von Ints erhalten, und dann wird das Minimum von diesen benötigt, um das Endergebnis zwischen allen Zeilen zu erhalten.
Das einzige, was diesen Code schlechter macht als die for
Loop-Version, ist, dass der gesamte row_minimums
Speicher auf einmal gespeichert wird, bevor er ausgeführt wird min_element
. Leider weiß ich nicht, wie ich das gleichzeitig machen kann, aber ich bin nicht der größte STL-Erwartung, also gibt es vielleicht einen Weg.
Andere Optionen, die Sie in Betracht ziehen könnten, bestehen darin, zuerst die 2D-Matrix zu einem 1D-Vektor zu verketten und dann darauf zu verwenden min_element
, oder die Option, die Sie in Ihre Bearbeitung aufgenommen haben, wo Sie min_element
dreimal aufrufen .
Außerdem scheint diese SO-Antwort interessante Informationen zu Lösungen zu enthalten, die die boost
Bibliothek verwenden, die möglicherweise besser sind, aber ich bin mir nicht sicher, was genau sie sind.
Nur ein bisschen einfacher: Mit std :: for_each iterieren Sie über jeden Vektor in der Matrix und erhalten das minimale Element davon. Wie min
durch Bezugnahme erfasst, erhalten Sie die min von allen von ihnen.
#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;
}