如何通过一个度量对元素进行排序

时间:2011-07-22 17:36:08

标签: c++ visual-studio-2010 function sorting iterator

在C ++中,我不太明白如何通过定义自定义函数来对元素进行排序。

Cppreference.com说比较功能:

  

comp - 比较函数,如果是第一个参数,则返回true   小于第二个。

     

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

当然我认为对于排序元素我需要定义一个度量,sort函数会根据度量对它们进行排序。

在我的实际例子中,我想根据它们与相机的距离来对图像文件进行排序。我有一个boost :: filesystem :: path的矢量链接到图像序列的目录

vector<boost::filesystem::path> path_vec

我自然会认为我需要写一个像

这样的函数
double z_distance( boost::filesystem::path filename, integer time )

什么会为所有元素返回一个double,并按每个帧的升序或降序对它们进行排序(从而改变参数中的时间)。

你能告诉我如何将这个返回单个值的函数转换为sort函数所需的bool函数吗?

如果我只能传递函数名称而不是对函数的完整调用,我怎么能传递参数

4 个答案:

答案 0 :(得分:3)

定义时

 bool nearer(const boost::filesystem::path& a, const boost::filesystem::path& b)
 {
   int somevalue = 0;
   return z_distance(a, somevalue) < z_distance(b, somevalue);
 }

你可以做到

 std::sort(path_vec.begin(), path_vec.end(), nearer);

但是,我不知道如何处理函数z_distance()的第二个参数。也许你可以从你的文件中获取它,或者你必须使用仿函数而不是函数进行比较。对于仿函数,请参阅@templatetypedef给出的答案。

由于您标记了VC ++ 10,您还可以使用C ++ 0x功能:编写lambda表达式(adhoc函数)来传递参数:

 int somevalue = 0;
 std::sort(path_vec.begin(), path_vec.end(), 
   [=](const boost::filesystem::path& a, const boost::filesystem::path& b) -> bool
   {
     return z_distance(a, somevalue) < z_distance(b, somevalue);
   }
 );

答案 1 :(得分:2)

有很多方法可以做到这一点。

如果您碰巧知道z_distance的第二个参数总是会有一些固定值,那么您可以通过编写实际进行比较的辅助函数将函数转换为比较器。例如:

bool CompareByDistance(const boost::filesystem::path& lhs,
                       const boost::filesystem::path& rhs) {
    return z_distance(lhs, kSecondArg) < z_distance(rhs, kSecondArg);
}

如果知道z_distance函数的第二个参数应该是什么,或者只能在运行时确定,那么您可能需要使用功能对象。函数对象(有时称为仿函数)是一个模仿常规函数的对象。您可以通过传入一些参数来调用它,但因为它是一个对象,除了参数之外,最终被调用的函数还可以访问本地状态。您可以构建的一个这样的函数对象可能如下所示:

class CompareByDistance {
public:
    /* Constructor takes in the time that you want to sort at,
     * then stores it for later.
     */
    CompareByDistance(int time) : mTime(time) {

    }

    /* This is the function call operator that is called when you try
     * treating a CompareByDistance object as a function.  Note how it
     * uses the mTime field as a parameter to `z_distance`.
     */
    bool operator()(const boost::filesystem::path& lhs,
                    const boost::filesystem::path& rhs) const {
        return z_distance(lhs, mTime) < z_distance(rhs, mTime);
    }
private:
    const int mTime; // Store mTime for later
};

现在,如果你想在某个时间t对所有内容进行排序,你可以写

sort(elems.begin(), elems.end(), CompareByDistance(t));

有关仿函数的更多信息,以及作为一个无耻的插件,这是我为一年前教过的C ++课程写的 a chapter on functors

希望这有帮助!

答案 2 :(得分:2)

重载operator<以返回&amp; A&lt; &amp; B,sort应该只使用begin(),end()和其他内容。

所以

 bool operator<(const SomeType& a, const SomeType& b)
 {
   return z_distance(a, 0) < z_distance(b, 0);
 }

你应该可以这样称呼它。

 std::vector<SomeType> vec;
 std::sort(vec.begin(), vec.end());

答案 3 :(得分:1)

好的,这就是你困惑的地方......

该函数一次比较两个元素,根据结果重新调整内部容器(树或其他)。所以,在STL函数中需要知道的所有C ++都是基于你的函数而不是元素B的elmement A.

所以,对于你所关心的一切,你的比较功能可以比较它们的距离,人的名字,或者你想要的任何东西。如果一个元素小于另一个元素,则该函数必须返回true,C ++将处理如何对其进行排序。