Почему лямбда-функция не работает с std :: min_element? - PullRequest
0 голосов
/ 07 апреля 2019

Я написал программу для поиска лексикографически минимальной строки в векторе строк, используя std::min_element, но я хочу получить минимальную строку, длина которой больше 1. Я пытался сделать std::min_element с лямбда-выражениями,но я получил ошибку компиляции.

Я пытался найти это, но не смог получить ничего, что решило бы проблему.

vector<string> names{"Jason", "Peter", "A", "Ac", "O"};
cout << *min_element(names.begin(), names.end(), [](string s) {return s.length() > 1;}) << '\n';

PS: Я ожидаю, что это напечатает "Ac".

Ответы [ 4 ]

2 голосов
/ 07 апреля 2019

Подпись функции сравнения std::min_element должна быть эквивалентна следующей.Вот причина, по которой вы получаете ошибку компиляции:

bool cmp(const Type1 &a, const Type2 &b);

Поскольку operator< перегружен для std::string для сравнения лексикографически, вы можете получить желаемый результат, отсортировав names с компаратором по умолчанию, а затем поиск первого элемента с длиной больше 1 следующим образом:

Live DEMO

std::vector<std::string> names{"Jason", "Peter", "A", "Ac", "O"};

std::sort(names.begin(), names.end());

const auto it = std::find_if(
                    names.cbegin(), names.cend(),
                    [](const std::string& str){return str.size() > 1;});

if(it != names.cend()){
    std::cout << *it << std::endl;
}

Если вы хотите сохранить исходный вектор names, скопируйте его перед сортировкой или используйте std::set следующим образом:

Live DEMO (std :: set)

std::vector<std::string> names{"Jason", "Peter", "A", "Ac", "O"};

std::set<std::string> s(names.cbegin(), names.cend());

const auto it = std::find_if(
                    s.cbegin(), s.cend(),
                    [](const std::string& str){return str.size() > 1;});

if(it != s.cend()){
    std::cout << *it << std::endl;
}
0 голосов
/ 07 апреля 2019

Вы можете определить функцию сравнения так, чтобы элемент длины, меньший или равный 1, был больше, чем более длинный элемент.

bool special_comparison(const std::string &s1, const std::string &s2)
{
    // Make a short string appears greater than a longer one.
    bool shortString1 = s1.size() <= 1;
    bool shortString2 = s2.size() <= 1;
    if (shortString1 != shortString2)
        return shortString2;

    // Regular comparison if both strings are short or both are long.
    return s1 < s2;
}

Если минимальный элемент имеет длину 1 (или 0),тогда это означает, что все элементы короткие.

Если данные не отсортированы, и вам нужно найти минимум один раз, это, вероятно, будет самым быстрым подходом.В противном случае (если вам нужно обрабатывать элементы по порядку), может быть лучше сначала отсортировать данные, как предложено в другом решении.

0 голосов
/ 07 апреля 2019

Проблема в последнем параметре. Он ожидает Compare и, будучи простым, Compare принимает два параметра и возвращает true или false. См. Определение шаблона min_element из cplusplus :

template <class ForwardIterator, class Compare>
ForwardIterator min_element (ForwardIterator first, ForwardIterator last, Compare comp);

Вы можете легко это исправить, добавив другой параметр и проигнорировав его.

vector<string> names{"Jason", "Peter", "A", "Ac", "O"};
cout << *min_element(names.begin(), names.end(), [](string s, string y) {return s.length() > 1;}) << '\n';

Вы также можете искать больше о Compare, так как вы будете использовать его довольно часто. Надеюсь, это поможет.

0 голосов
/ 07 апреля 2019

Хотя ответ на этот вопрос и не дан, решение состоит в том, чтобы сначала отсортировать вектор по длине строки, а затем использовать лямбда-функцию в std::find_if

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...