2011-07-22 83 views
3

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

Cppreference.com说,对于比较功能:

补偿 - 如果第一个参数 小于第二返回true比较函数。

布尔CMP(常量的Type1 &一个,常量类型2 & b)中;

自然我认为用于分拣元件我需要定义的措施,以及排序函数将取决于对它们进行排序在措施。

在我的实际例子中,我想根据它们距相机有多远来对图像文件进行排序。我有提高文件系统::路径::链接到图像序列

vector<boost::filesystem::path> path_vec 

的目录向量,我自然觉得我需要写像

double z_distance(boost::filesystem::path filename, integer time) 

什么会返回一个双重功能对于所有元素,按照每帧的升序或降序对它们进行排序(因此参数中的变化时间)。

你能告诉我应该如何将这个返回单一值的函数转换为排序函数所需的布尔函数?

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

回答

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)); 

关于仿函数的详细信息,并作为一个无耻的插件,这里的a chapter on functors,我写了一年前我教过的C++课程。

希望这会有所帮助!

1

好,这也正是你困惑......

功能两个因素在同一时间进行比较,调整基础上,因此内部容器(树或其他)。因此,所有C++在STL函数中需要知道的是,基于你的函数,小于元素B.

因此,对于您所关心的所有问题,您的比较功能可以比较它们的距离,人名或任何你想要的。如果一个元素少于另一个元素,函数只需返回true,C++将处理如何对它进行排序。

+0

PS:该函数将在您的STL容器的整个内容中运行很多次,每次两个elemetns - 对不起,我应该在帖子中说过。这就是为什么它不需要返回一个double,而一个bool就足够了。 –

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表达式(自组织功能)来传递参数:

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

我建议最好的做法是使用'const TYPE&'而不是'TYPE'作为复制操作符,否则会被调用很多。所以 '布尔较近(常量升压::文件系统::路径&一个,常量booost ::文件系统::路径和b)...' 或在lambda情况下, '[=](常量升压:: filesystem :: path&a,const booost :: filesystem :: path&b)...' – Soren

+0

@Soren:我同意,更改了代码。在写作时我有点懒惰,并且在展示一个概念时不想打包太多。 –

2

过载operator<返回& A < & B,排序应该只用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()); 
相关问题