Лучший способ найти самый маленький по размеру элемент вектора из 2D вектора - PullRequest
2 голосов
/ 08 июля 2019

Я пытаюсь найти элемент vector<int> самого маленького размера из vector<vector<int>>.

Вот мой код, который работает, но он повторяет вектор дважды.

#include <iostream>
#include <vector>
#include <limits>

int main()
{
    std::vector<std::vector<int>> foo = {{1,2,3,4}, {1,2}, {1,2,3,4,5}, {1,2,3}};
    size_t smallestNumElems = std::numeric_limits<size_t>::max();
    for (size_t i = 0; i < foo.size(); ++i)
    {
        const size_t numElems = foo[i].size();
        if (smallestNumElems > numElems)
            smallestNumElems = numElems;
    }
    for (size_t i = 0; i < foo.size(); ++i)
    {
        if (smallestNumElems == foo[i].size())
        {
            for (size_t j = 0; j < foo[i].size(); ++j)
                std::cout << foo[i][j] << '\n';
            break;
        }
    }
}

Результат:

1
2
Program ended with exit code: 0

Есть ли лучший способ получить тот же результат?

Ответы [ 3 ]

5 голосов
/ 08 июля 2019

Вариант 1:

int main()
{
    std::vector<std::vector<int>> foo = {{1,2,3,4}, {1,2}, {1,2,3,4,5}, {1,2,3}};
    size_t smallestNumElems = std::numeric_limits<size_t>::max();
    std::vector<int>* smallestEntry = nullptr; // Store a reference to the smallest entry in here
    for (size_t i = 0; i < foo.size(); ++i)
    {
        const size_t numElems = foo[i].size();
        if (smallestNumElems > numElems) {
            smallestNumElems = numElems;
            smallestEntry = &foo[i];
        }
    }
    for (size_t i = 0; i < smallestEntry->size(); ++i)
       std::cout << smallestEntry->at(i) << '\n';
}

Вариант 2:

#include <algorithm>
// ... Stuff
int main()
{
    std::vector<std::vector<int>> foo = {{1,2,3,4}, {1,2}, {1,2,3,4,5}, {1,2,3}};

    auto& smallest = *std::min_element(foo.begin(), foo.end(), 
        [](std::vector<int> const& a, std::vector<int> const& b) { // <- could replace std::vector<int> with auto
            return a.size() < b.size(); 
        }
    );

    for (size_t i = 0; i < smallest.size(); ++i)
       std::cout << smallest.at(i) << '\n';
}
5 голосов
/ 08 июля 2019

Есть ли лучший способ получить тот же результат?

Используйте стандартную библиотеку, т. Е. std::min_element и настройте сравнение с помощью lamdba.

const auto smallestSizeVec = std::min_element(foo.cbegin(), foo.cend(),
    [](const auto& v1, const auto& v2) { return v1.size() < v2.size(); });

std::cout << "The smallest vector has size " << smallestSizeVec->size() << "\n";
2 голосов
/ 08 июля 2019

Чтобы сделать код более читабельным, лучше использовать стандартные алгоритмы.

Например

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

int main() 
{
    std::vector<std::vector<int>> foo = 
    {
        { 1, 2, 3, 4}, { 1, 2 }, { 1, 2, 3, 4, 5 }, { 1, 2, 3 }

    };

    auto min_size = []( const auto &v1, const auto &v2 )
    {
        return v1.size() < v2.size();
    };

    auto it = std::min_element( std::begin( foo ), std::end( foo ), min_size );

    for ( const auto &value : *it ) std::cout << value << ' ';
    std::cout << '\n';

    return 0;
}

Вывод программы:

1 2 

Если ваш компиляторподдерживает стандарт C ++ 17, тогда лямбда-выражение также можно записать в виде

    auto min_size = []( const auto &v1, const auto &v2 )
    {
        return std::size( v1 ) < std::size( v2 );
    };

Если использовать циклы, как вы делаете, тогда для экранирования двух циклов, которые находят вектор с минимальным размером, вы можете написать

#include <iostream>
#include <vector>

int main() 
{
    std::vector<std::vector<int>> foo = 
    {
        { 1, 2, 3, 4}, { 1, 2 }, { 1, 2, 3, 4, 5 }, { 1, 2, 3 }

    };

    using size_type = std::vector<std::vector<int>>::size_type;

    size_type min_vector = 0;

    for ( size_type i = 1; i < foo.size(); ++i )
    {
        if ( foo[i].size() < foo[min_vector].size() )
        {
            min_vector = i; 
        }
    }

    for ( const auto &value : foo[min_vector] ) std::cout << value << ' ';
    std::cout << '\n';

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