简体   繁体   English

对不同变量的向量使用排序函数

[英]Using the sort function on vectors on different variables

I have data that has been given in coordinates.我有坐标中给出的数据。 I made their classes and the classes are made of this:我做了他们的课,这些课是由这个组成的:

Point2D (int x, int y)

Point3D (int z) //#include Point2D.h

Line2D (Point2D pt1, Point2D pt2)

Line3D (Point3D pt1, Point3D pt2)

Now, I am supposed to be able to sort the data according to any filtering criteria (each class is a filtering criterion), any sorting criteria ( x, y, z , or their product) and sorting order (either ascending or descending) The filtering criteria specify which set of records to be displayed.现在,我应该能够根据任何过滤条件(每个类都是一个过滤条件)、任何排序条件( x, y, z或它们的乘积)和排序顺序(升序或降序)对数据进行排序。过滤条件指定要显示的记录集。

I've created a generic sort algorithm, but I am supposed to be using the sort function from the STL algorithm.我已经创建了一个通用的排序算法,但我应该使用 STL 算法中的排序函数。 I'm pasting my algo below, but can someone simplify it using the std::sort function.我在下面粘贴我的算法,但有人可以使用std::sort函数简化它。

void sort(
   vector<Point2D*>& point2DList,
   vector<Point3D*>& point3DList,
   vector<Line2D*>& line2DList,
   vector<Line3D*>& line3DList,
   string filterCriteria, string sortingCriteria, string sortingOrder)
{
   if (filterCriteria == "Point2D")
   {
      for (int i = 0; i < (int)point2DList.size() - 1; i++)
      {
         int index = i;
         for (int j = i + 1; j < point2DList.size(); j++)
         {
            if (sortingOrder == "ASC")
            {
               if ((sortingCriteria == "x-ordinate" && point2DList[index]->getX() > point2DList[j]->getX()) || 
                  (sortingCriteria == "y-ordinate" && point2DList[index]->getY() > point2DList[j]->getY()))
                  index = j;
            }
            else if (sortingOrder == "DSC")
            {
               if ((sortingCriteria == "x-ordinate" && point2DList[index]->getX() < point2DList[j]->getX()) || 
                  (sortingCriteria == "y-ordinate" && point2DList[index]->getY() < point2DList[j]->getY()))
                  index = j;
            }
         }
         Point2D* ptr = point2DList[i];
         point2DList[i] = point2DList[index];
         point2DList[index] = ptr;
      }
   }
}

I have only pasted the first part of the algo that involves the Point2D objects, the same flow I have applied for the other 3 classes as well.我只粘贴了涉及Point2D对象的算法的第一部分,我也为其他 3 个类应用了相同的流程。

Fist of all to my understanding, you are using a single sort function (non-template) for sorting different data structure.首先,据我所知,您正在使用单个sort函数(非模板)对不同的数据结构进行排序。 This is not how you make the generic sort function.这不是您制作通用排序功能的方式。 You need to go for function templates .你需要去寻找功能模板

Secondly, the vectors of raw-pointers to those data structure does not look appropriate.其次,指向这些数据结构的原始指针的向量看起来不合适。 The std::vector created/ allocates it's underline data dynamically in free storage, meaning you do not need to put each its elements in manually created memory. std::vector created/ 在空闲存储中动态分配它的下划线数据,这意味着您不需要将每个元素放入手动创建的内存中。 If that can not be avoided, I would suggest smart pointers rather than raw pointers there.如果无法避免,我会建议使用智能指针而不是原始指针。

Thirdly the filterCriteria , sortingOrder , and sortingCriteria could have been enum s rather than std::string s.第三, filterCriteriasortingOrdersortingCriteria可能是enum而不是std::string

Following is the modified sort function, which actually only considers your requirement of using std::sort .以下是修改后的sort函数,它实际上只考虑了您使用std::sort要求。 Also note that I have used, lambda functions for the custom sorting criteria, which you could read more here: What is a lambda expression in C++11?另请注意,我已经使用了用于自定义排序标准的lambda 函数,您可以在此处阅读更多内容: 什么是 C++11 中的 lambda 表达式?

// enumerations  for case checking!
enum class FilterCriteria { Point2D = 0, Point3D/*, other cases*/ };
enum class SortingCriteria { x_ordinate = 0, y_ordinate };
enum class SortingOrder { ASC = 0, DSC };

void sort(
   std::vector<Point2D*>& point2DList,
   std::vector<Point3D*>& point3DList,
   std::vector<Line2D*>& line2DList,
   std::vector<Line3D*>& line3DList,
   const FilterCriteria filterCriteria,
   const SortingOrder sortingOrder,
   const SortingCriteria sortingCriteria)
{
   const auto xLessCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->x < rhs->x; };
   const auto yLessCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->y < rhs->y; };
   const auto xGreaterCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->x > rhs->x; };
   const auto yGreaterCompare = [](const Point2D* lhs, const Point2D* rhs) { return lhs->y > rhs->y; };

   switch (filterCriteria)
   {
   case FilterCriteria::Point2D:
   {
      if (sortingOrder == SortingOrder::ASC)
      {
         if (sortingCriteria == SortingCriteria::x_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), xGreaterCompare);
         else if (sortingCriteria == SortingCriteria::y_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), yGreaterCompare);
      }
      else if (sortingOrder == SortingOrder::DSC)
      {
         if (sortingCriteria == SortingCriteria::x_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), xLessCompare);
         else if (sortingCriteria == SortingCriteria::y_ordinate)
            std::sort(point2DList.begin(), point2DList.end(), yLessCompare);

      }
      break;
   }
   case FilterCriteria::Point3D: {
      // ... code
      break;
   }
   default: break;
   };
}

See here for an example code onlone参见此处获取示例代码

I don't have your class definitions, so i made theese, i hope they are like yours.我没有你的类定义,所以我做了这些,我希望它们和你的一样。

If you want to use std::sort you have 2 options:如果你想使用std::sort你有两个选择:

  1. define less ( < ) operator for class ( or structure )为类(或结构)定义 less ( < ) 运算符
  2. pass lambda, as a less comparator传递 lambda,作为较少的比较器

1 option is used if sorting used many times, or if classes are stored in containers, that requires less operator (like std::set or std::map ) 2 option is good if you sort some structer only in one place in whole code and you need it inline, or you have to overload currently specifed less operator如果多次使用排序,或者如果类存储在容器中,需要较少的运算符(如std::setstd::map ),则使用 1 选项 2 如果您在整个代码中仅在一个地方对某个结构体进行排序,则使用 2 选项并且您需要内联,或者您必须重载当前指定的 less 运算符

Here is code with both options, hope it helps.这是两个选项的代码,希望它有所帮助。 If anything makes you struggle, feel free to comment如果有什么让你挣扎,请随时发表评论

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

struct Point2D
{
    int x;
    int y;

    Point2D(const int x, const int y) : x{x}, y{y} {}

    inline friend bool operator<(const Point2D& p1, const Point2D& p2)
    {
        return ( p1.x == p2.x ? p1.y < p2.y : p1.x < p2.x );
    }
};

// print operator
std::ostream& operator<<(std::ostream& o, const Point2D& p)
{
    return o << "( x=" << p.x << ", y=" << p.y << ")";
}

struct Point3D : public Point2D
{
    Point3D(const int x, const int y, const int z) : Point2D{ x,y }, z{z} {}

    int z;
};

// print operator
std::ostream& operator<<(std::ostream& o, const Point3D& p)
{
    return o << "( z=" << p.z << ", x=" << p.x << ", y=" << p.y << ")";
}

// supportive functions for printing
template<typename T>
void print_collection( const std::vector<T>& vec, const char* collection_name )
{
    std::cout << collection_name << ": ";
    for(const auto& var : vec)
        std::cout << var << ", ";

    std::cout << std::endl;
}

template<typename T>
void print_ptr_collection( const std::vector<T>& vec, const char* collection_name )
{
    std::cout << collection_name << ": ";
    for(const auto& var : vec)
        std::cout << *var << ", ";

    std::cout << std::endl;
}

// support functions for random numbers
int rng()
{
    std::random_device engine;
    std::uniform_int_distribution<int> ranges{ -100, 100 };
    return ranges(engine);
}

int main()
{
    std::vector<Point2D> vec1; vec1.reserve(5);
    std::vector<Point3D*> vec2; vec2.reserve(5);

    // fill
    for(int i = 0; i < 5; i++)
    {
        vec1.emplace_back( rng(), rng() );
        vec2.emplace_back( new Point3D{ rng(), rng(), rng() } );
    }

    // print unsorted
    print_collection( vec1, "vec1 unsorted");
    print_ptr_collection( vec2, "vec2 unsorted");

    // sort with std::sort
    std::sort( vec1.begin(), vec1.end() );
    std::sort( vec2.begin(), vec2.end(), [](const Point3D* p1, const Point3D* p2) -> bool {
        return ( p1->z == p2->z ? (*p1) < (*p2) : p1->z < p2->z );
    } );

    // print sorted
    print_collection( vec1, "vec1 sorted" );
    print_ptr_collection( vec2, "vec2 sorted" );

    // cleanup
    for(int i = 0; i < vec2.size(); i++)
    {
        delete vec2[i];
        vec2[i] = nullptr;
    }

}

This is the output:这是输出:

vec1 unsorted: ( x=3, y=66), ( x=-1, y=-65), ( x=-9, y=-70), ( x=29, y=16), ( x=32, y=56), 
vec2 unsorted: ( z=-51, x=-57, y=-87), ( z=58, x=49, y=43), ( z=-71, x=-63, y=-87), ( z=23, x=-22, y=13), ( z=-57, x=94, y=-7), 
vec1 sorted: ( x=-9, y=-70), ( x=-1, y=-65), ( x=3, y=66), ( x=29, y=16), ( x=32, y=56), 
vec2 sorted: ( z=-71, x=-63, y=-87), ( z=-57, x=94, y=-7), ( z=-51, x=-57, y=-87), ( z=23, x=-22, y=13), ( z=58, x=49, y=43), 

Edit: forgot to add deleteion of pointers at the end :)编辑:忘了在最后添加删除指针:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM