C ++ вектор двойной сортировки по переменным в классе - PullRequest
0 голосов
/ 25 октября 2018

У меня есть вектор объекта пользовательского типа, и я хочу отсортировать вектор по первой строковой переменной, а затем по второй строковой переменной.

class MyClass{
  private:
    string a;
    string b;
    int x;
    double y;
}

У меня есть вектор в основном коде, который имеетданные уже разбиты на любое количество элементов в зависимости от файла.

int main(){
  vector<MyClass> data;

  // Code that fills the data variable.  This all works and can be displayed via print function

  /*CODE TO SORT BY THE FIRST STRING THEN SORT AGAIN BY THE SECOND STRING
   *
   *  -- Sort code here --
   *
   */

  return 0;
}

Мой вопрос в 2 раза:

1) Как вы делаете сортировку вектора на основе переменнойвнутри этого вектора?Вектор должен быть отсортирован по первой строке в классе (строка с меткой a).

2).Как бы вы дополнительно отсортировали вектор, чтобы после сортировки первой строки отсортировать вторую строку, чтобы выходные данные выглядели примерно так (для всех намерений и целей числа во второй строке (строка b) являются строками, а не целыми числами):

string a: a    string b: 1
string a: a    string b: 2
string a: a    string b: 3
string a: a    string b: 4
string a: b    string b: 1
string a: b    string b: 2
string a: b    string b: 3
string a: b    string b: 4

Ответы [ 5 ]

0 голосов
/ 25 октября 2018

Вы можете передать пользовательский компаратор.std::tie может помочь создать его просто, поскольку std::tuple имеет лексикографическое сравнение (при условии, что его внутренний тип можно сравнить):

std::vector<MyClass> data/* = ..*/;

auto as_tuple_a_b = [](const MyClass& c) { return std::tie(c.a, c.b); };
std::sort(data.begin(), data.end(),
          [](const MyClass& lhs, const MyClass& rhs) {
              return as_tuple_a_b (lhs) < as_tuple_a_b(rhs);
          });

Если это имеет смысл, вы можете реализовать operator < для своеготип:

bool operator< (const MyClass& lhs, const MyClass& rhs) {
    auto as_tuple = [](const MyClass& c) { return std::tie(c.a, c.b, c.x, c.y); };
    return as_tuple (lhs) < as_tuple_a_b(rhs);
}
0 голосов
/ 25 октября 2018

Это упрощенная версия моего рабочего кода:

MyClass.h

class MyClass{
  public:
    friend bool operator > (const MyClass& lhs, const MyClass& rhs);

  private:
    string a;
    string b;
    int x;
    double y;
}

MyClass.cpp

bool operator < (const MyClass& lhs, const MyClass& rhs){
    return (lhs.a == rhs.b) ? (lhs.b < rhs.b) : (lhs.a < rhs.b);
} 

Main.cpp

int main(){
  vector<MyClass> data;  // Already filed data

  sort(data.begin(), data.end());

  return 0;
}
0 голосов
/ 25 октября 2018

std::sort поддерживает два способа сравнения элементов: 1. bool operator<(YourClass const & lhs, YourClass const & rhs); 2. компаратор, который передается в std::sort

Как провести лексикографическое сравнение вашего класса.Лучший способ использовать std::tuple, обеспечивающий такие функциональные возможности:

#include <iostream>
#include <algorithm>
#include <tuple>
#include <vector>
#include <string>

struct MyClass{
    std::string a;
    std::string b;
    int x;
    double y;
    std::tuple<std::string const &, std::string const &> asTupleForComparison() const
    {
        return std::tie(a, b);
    }
};


int main() 
{ 
    std::vector<MyClass> vec = {{std::string("a"), std::string("b"), 0, 0.0}, 
                                {std::string("a"), std::string("a"), 0, 0.0}};
    std::sort(vec.begin(), vec.end(), [](MyClass const & lhs, MyClass const & rhs){
        return lhs.asTupleForComparison() < rhs.asTupleForComparison();
    });

    for (auto const & item : vec)
    {
        std::cout << item.a << " " << item.b << "\n";
    }
    return 0; 
}

, для решения проблемы частных переменных используйте friend:

class MyClass{
    std::string a;
    std::string b;
    int x;
    double y;
    std::tuple<std::string const &, std::string const &> asTupleForComparison() const
    {
       return std::tie(a, b);
    }
    friend bool compare(MyClass const & lhs, MyClass const & lhs)
    {
        return lhs.asTupleForComparison() < rhs.asTupleForComparison();
    }
};
0 голосов
/ 25 октября 2018

В дополнение к другим методам вы можете даже объявить пользовательский компаратор в friend class compare внутри MyClass.

Примерно так:

class MyClass{
  private:
   string a;
   string b;
   int x;
   double y;
  public:
   friend class compare;
}

Проверьте этот стекопоток ответьте для получения более подробной информации о том, как определить пользовательские компараторы.

0 голосов
/ 25 октября 2018

Сделайте a и b общедоступными и попробуйте что-то вроде этого:

std::sort(data.begin(), data.end(), [](const MyClass& v1, const MyClass& v2) {
        return (v1.a == v2.a) ? (v1.b < v2.b) : (v1.a < v2.a);   
    });

Вы можете держать их в секрете и использовать getter для получения их значения.Как упоминалось в ZDF, вы также можете создать оператор <.добавить следующее к Myclass:

MyClass {
...
public:
    bool operator<(const MyClass& v2) const {
        return (a == v2.a) ? (b < v2.b) : (a < v2.a);   
    }
}

Затем sort, например:

std::sort(data.begin(), data.end());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...