示例例程:
const Armature* SceneFile::findArmature(const Str& name){
for (int i = 0; i < (int)armatures.size(); i++)
if (name == armatures[i].name)
return &armatures[i];
return 0;
}
例程的目的是(显然)根据元素的成员变量在元素数组中查找值,其中比较成员变量和外部“键”是搜索条件。
一种方法是循环遍历数组。另一种是使用某种“map”类(std :: map,某种矢量排序值+ binarySearch等)。也可以为std :: find或std :: for_each创建一个类,并使用它来“包装”迭代循环。
有什么其他方法可以做到这一点?
我正在寻找提取所需元素的替代方法/技术。 理想情况下 - 我正在寻找语言结构,或模板“组合”,或者我不知道的编程模式会将整个循环或整个函数折叠成一个语句。最好使用标准的C ++ / STL特性(没有C ++ 0x,直到它成为新标准)并且不必编写额外的辅助类(即,如果存在辅助类,则应该从现有模板生成它们)。
即。类似于std :: find的地方比较基于类成员变量,并且使用标准模板函数提取变量,或者如果可以选择变量(与“key”(“name”)比较的变量)作为参数。
问题的目的是发现/找到我还不知道的语言特征/编程技术。我怀疑可能是一个类似于for_each的适用的构造/ tempalte / function /技术,并且知道这种技术可能很有用。这是询问的主要原因。
想法?
答案 0 :(得分:2)
如果您有权访问Boost或其他tr1实现,则可以使用bind来执行此操作:
const Armature * SceneFile::findArmature(const char * name) {
find_if(armatures.begin(), armatures.end(),
bind(_stricmp, name, bind(&string::c_str, bind(&Armature::name, _1))) == 0);
}
警告:我怀疑很多人会承认这会更短,但声称它在更优雅/更简单的标准上失败了。
答案 1 :(得分:1)
当然看起来像std::find_if的情况 - 作为谓词,你可以使用例如一个合适的bind1st。我不愿意多说这些作业很多 ...; - )。
答案 2 :(得分:1)
为什么5行?清洁没有附加数字。事实上,干净的代码可能会在实用程序类中占用更多行,然后可以反复使用它们。不要不必要地限制自己。
class by_name
{
public:
by_name(const std::string& pName) :
mName(pName)
{}
template <typename T>
bool operator()(const T& pX)
{
return pX.name == pName;
}
private:
std::string mName;
};
然后:
const Armature* SceneFile::findArmature(const char* name)
{
// whatever the iterator type name is
auto iter = std::find_if(armatures.begin(), armatures.end(), by_name(name));
return iter == armatures.end() ? 0 : &(*iter);
}
在限制范围内:
class by_name { public: by_name(const std::string& pName) : mName(pName) {} template <typename T> bool operator()(const T& pX) { return pX.name == pName; } private: std::string mName; };
然后:
const Armature* SceneFile::findArmature(const char* name)
{
// whatever the iterator type name is
auto iter = std::find_if(armatures.begin(), armatures.end(), by_name(name));
return iter == armatures.end() ? 0 : &(*iter);
}
:)
C ++ 0x有基于范围的for循环,我认为这将是最优雅的解决方案:
const Armature* SceneFile::findArmature(const std::string& pName) const
{
for (auto a : armatures)
{
if (a.name = pName) return &a;
}
return 0;
}
答案 3 :(得分:0)
您可能需要使用STL地图。它使您可以使用键获取元素。你的钥匙就是电枢的名字。
http://www.cplusplus.com/reference/stl/map/
编辑:: D
一个班轮B - )
const Armature* SceneFile::findArmature(const Str& name){for (int i = 0; i < (int)armatures.size(); i++) if(name == armatures[i].name) return &armatures[i]; return 0;}
答案 4 :(得分:-4)
神圣的shiz,你在使用_stricmp?失败。另外,你实际上没有告诉我们矢量的类型或涉及的任何变量,所以这只是猜测。
const Armature* SceneFile::findArmature(const std::string& lols) {
for(auto it = armatures.begin(); it != armatures.end(); it++) {
if (boost::iequals(lols, (*it).name))
return &(*it);
return NULL;
}
最终,如果你需要这个,你应该在std :: map中放置它们的骨架或指针。如果你正在搜索它,它就是一个错误的容器,当收集是重要的而不是任何发现行为时,它们是最好的。
编辑使用std :: string引用。