Поиск минимального ненулевого элемента массива

Есть массив std::vector<unsigned int> mas, нужно найти минимальный среди ненулевых элементов.

Просто минимальный легко находится таким способом:

auto min_pos = std::min_element (mas.begin (), mas.end (), [&](unsigned int a, unsigned int b){ return a < b; });
unsigned int m = *min_pos;

Я специально написал с лямбдой, потому что (мне кажется) нужно что-то хитрое в неё добавить, что именно - что-то не могу сообразить.

Модифицировать массив нельзя, если бы было можно - я бы сделал ему std::remove и далее по накатанной.


Ответы (3 шт):

Автор решения: zcorvid

Придумал такой вариант

auto min_pos = std::min_element (mas.begin (), mas.end (), [&](int a, int b){ return a != 0 && a < b; });
if (min_pos != mas.end ())
    std::cout << "минимум = " << mas[*min_pos] << std::endl;
else
    std::cout << "нету ненулевых элементов" << std::endl;

Но, возможно, есть более правильный способ?

→ Ссылка
Автор решения: Stanislav Volodarskiy

Зададим полный порядок, в котором нулевые значения больше любых других:

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> a = {0, 1, 2};
    auto min_pos = std::min_element(a.begin(), a.end(), [](auto a, auto b){
        // nonzero < zero
        if ((a != 0) && (b == 0)) {
            return true;
        }
        // !(zero < nonzero)
        if ((a == 0) && (b != 0)) {
            return false;
        }
        // zero    < zero    OR
        // nonzero < nonzero
        return a < b;
    });
    std::cout << *min_pos << '\n';
}

Лямбда рефакторится до вида, который Harry уже привел в комментарии и ответе:

    auto min_pos = std::min_element(a.begin(), a.end(), [](auto a, auto b){
        return (a != 0) && ((b == 0) || (a < b));
    });
→ Ссылка
Автор решения: Harry

Буду предельно краток :), вот она, лямбда:

[&](int a, int b){ return a && (!b || a < b); }
→ Ссылка