вектор сортировки < вариант < & hellip; > > неправильно работает через оператора <

Мне нужна была простая в использовании библиотека C ++ для разбора CSV-файлов, но я не мог найти ее, поэтому я закончил ее создание. Rapidcsv - это библиотека заголовков C ++ 11, которая дает прямой доступ к разбору столбцов (или строк) в виде векторов в выбранном типе данных. Например:

#include 
#include 
#include 

int main()
{
  rapidcsv::Document doc("../tests/msft.csv");

  std::vector close = doc.GetColumn("Close");
  std::cout << "Read " << close.size() << " values." << std::endl;
}

2
задан Jonas B. 16 January 2019 в 18:11
поделиться

2 ответа

Вы неправильно понимаете, как работает std::variant operator<. Сначала он сравнивает индексы и только если индексы равны, он сравнивает значения: https://en.cppreference.com/w/cpp/utility/variant/operator_cmp . Для неравных индексов он возвращает true, если индекс по первому варианту меньше, чем по второму.

0
ответ дан SergeyA 16 January 2019 в 18:11
поделиться

Это:

std::sort(std::begin(shapes), std::end(shapes));

использует сравнение по умолчанию sort, то есть operator<. operator< в std::variant определяется как как , сравнивая по индексам сначала , а затем, если оба варианта содержат одну и ту же альтернативу, сравнивая базовые значения.

Другими словами:

using V = std::variant<char, int>;
V v1(static_cast<char>(42));  // holds a char
V v2(15);                     // holds an int
v1 < v2;                      // this is true, because 'char' comes before 'int'

Итак, когда вы сортируете свои variant, вы не сортируете по областям. Вы эффективно сортируете по кортежу (index, area). Который мы могли бы написать длинным путем:

std::sort(std::begin(shapes), std::end(shapes),
    [](auto const& lhs, auto const& rhs)
    {
        auto tied = [](auto const& x) {
            return std::make_tuple(
                // the index
                x.index(),
                // the area
                std::visit([](auto const& e){ return e.area(); }, x)
                );
        };
        return tied(lhs) < tied(rhs);
    });

Это дает тот же порядок, что и в вашем первоначальном примере. А затем, если вы удалите x.index() часть кортежа, вы получите тот порядок, который вам нужен.

Но короче просто использовать многократное посещение:

std::sort(std::begin(shapes), std::end(shapes),
    [](auto const& lhs, auto const& rhs)
    {
        std::visit([](auto const& x, auto const& y){
            return x.area() < y.area();
        }, lhs, rhs);
    });

, которое станет еще короче в C ++ 20 с диапазонами и проекциями:

std::ranges::sort(shapes, std::less(), [](auto const& x){
    return std::visit([](auto const& e){ return e.area(); }, x);
    });
0
ответ дан Barry 16 January 2019 в 18:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: