C++ STL列表-如何通过对象字段查找列表元素
我有一份清单:C++ STL列表-如何通过对象字段查找列表元素,c++,list,stl,C++,List,Stl,我有一份清单: list<Unit *> UnitCollection; 如何通过uCode搜索UnitCollection列表并返回相应的元素和迭代器 在伪代码中,它看起来像这样: for every item in my UnitCollection: if the unit.isUnit(someUnitIpass) do something else next unit struct predicate { predicate( const
list<Unit *> UnitCollection;
如何通过uCode搜索UnitCollection列表并返回相应的元素和迭代器
在伪代码中,它看起来像这样:
for every item in my UnitCollection:
if the unit.isUnit(someUnitIpass)
do something
else
next unit
struct predicate
{
predicate( const std::string &uCode ) : uCode_(uCode) {}
bool operator() ( Unit *u )
{
return u->isUnit( uCode_ )
}
private:
std::string uCode_;
};
predicate pred("uCode");
std::list<Unit*>::iterator i;
i = std::find_if( UnitCollection.begin(), UnitCollection.end(), pred );
我已经研究了find方法,但是如果有意义的话,我不确定是否可以传入布尔方法而不是搜索项参数。看看
如果可以使用boost,那么可以将其与boost::lambda一起使用
或者你可以编写自己的函子
struct isUnitor // : public std::unary_function<Unit*, bool> -- this is only needed for the negation below
{
string arg;
isUnitor(const string& s) : arg(s) {}
bool operator()(Unit* u) const { return u->isUnit(arg); }
};
std::find_if(...begin... , ...end... , isUnitor("code"))
看一看
如果可以使用boost,那么可以将其与boost::lambda一起使用
或者你可以编写自己的函子
struct isUnitor // : public std::unary_function<Unit*, bool> -- this is only needed for the negation below
{
string arg;
isUnitor(const string& s) : arg(s) {}
bool operator()(Unit* u) const { return u->isUnit(arg); }
};
std::find_if(...begin... , ...end... , isUnitor("code"))
您可以按照jpalecek的建议查看一下,然后使用查找从find_if返回的迭代器与UnitCollection.begin之间的距离,该距离应该是列表中元素的索引
对于谓词,您可以编写如下函数对象:
for every item in my UnitCollection:
if the unit.isUnit(someUnitIpass)
do something
else
next unit
struct predicate
{
predicate( const std::string &uCode ) : uCode_(uCode) {}
bool operator() ( Unit *u )
{
return u->isUnit( uCode_ )
}
private:
std::string uCode_;
};
predicate pred("uCode");
std::list<Unit*>::iterator i;
i = std::find_if( UnitCollection.begin(), UnitCollection.end(), pred );
然后像这样使用它:
for every item in my UnitCollection:
if the unit.isUnit(someUnitIpass)
do something
else
next unit
struct predicate
{
predicate( const std::string &uCode ) : uCode_(uCode) {}
bool operator() ( Unit *u )
{
return u->isUnit( uCode_ )
}
private:
std::string uCode_;
};
predicate pred("uCode");
std::list<Unit*>::iterator i;
i = std::find_if( UnitCollection.begin(), UnitCollection.end(), pred );
或者至少我认为这是一种方法。您可以按照jpalecek的建议查看一下,然后使用查找if和UnitCollection.begin返回的迭代器之间的距离,该距离应该是列表中元素的索引
对于谓词,您可以编写如下函数对象:
for every item in my UnitCollection:
if the unit.isUnit(someUnitIpass)
do something
else
next unit
struct predicate
{
predicate( const std::string &uCode ) : uCode_(uCode) {}
bool operator() ( Unit *u )
{
return u->isUnit( uCode_ )
}
private:
std::string uCode_;
};
predicate pred("uCode");
std::list<Unit*>::iterator i;
i = std::find_if( UnitCollection.begin(), UnitCollection.end(), pred );
然后像这样使用它:
for every item in my UnitCollection:
if the unit.isUnit(someUnitIpass)
do something
else
next unit
struct predicate
{
predicate( const std::string &uCode ) : uCode_(uCode) {}
bool operator() ( Unit *u )
{
return u->isUnit( uCode_ )
}
private:
std::string uCode_;
};
predicate pred("uCode");
std::list<Unit*>::iterator i;
i = std::find_if( UnitCollection.begin(), UnitCollection.end(), pred );
或者至少我认为这是一种方法。首先是一个无关紧要的评论
您可以将访问器函数更改为更简单的形式
return unitCode == uCode;
现在谈谈我们来这里的目的
最好是查找元素的位置,而不是其索引。从其索引获取元素是一个On操作,而从其位置获取元素是一个O1操作。因此,在STL和boost::bind的帮助下:
然后,您可以调用std::find_(如果愿意):
还有一点性能方面的考虑
还有一件事:我不知道uCode看起来是什么样子,但是如果它们很大,那么您可以通过维护这些字符串的哈希值来加快速度,以便在搜索谓词中只比较哈希值。散列可能是正则整数:比较整数非常快
另外一件事:如果你经常运行这个搜索过程,你也可以考虑改变容器类型,因为这确实是一个昂贵的过程:按照列表的长度顺序。
第一个无关紧要的评论。 您可以将访问器函数更改为更简单的形式return unitCode == uCode;
现在谈谈我们来这里的目的
最好是查找元素的位置,而不是其索引。从其索引获取元素是一个On操作,而从其位置获取元素是一个O1操作。因此,在STL和boost::bind的帮助下:
然后,您可以调用std::find_(如果愿意):
还有一点性能方面的考虑
还有一件事:我不知道uCode看起来是什么样子,但是如果它们很大,那么您可以通过维护这些字符串的哈希值来加快速度,以便在搜索谓词中只比较哈希值。散列可能是正则整数:比较整数非常快
另外一件事:如果你经常运行这个搜索过程,你也可以考虑改变容器类型,因为这确实是一个昂贵的过程:按照列表的长度顺序。
你的谓词可能看起来像:struct unit_predicate {
unit_predicate(const string& s): str(s) {}
bool operator()(const Unit* unit) const {
return unit->isUnit(str);
}
const string& str;
};
UnitCollection::const_iterator unit = std::find_if(units.begin(), units.end(), unit_predicate("Some Unit"));
其他几点意见:
isUnit函数最好按常量引用获取字符串,以避免不必要的副本
你说你想返回一个项目的索引;对于链表来说,这通常是不合理的,因为您无法通过索引获取项目。如果您想通过索引处理它们,那么std::vector可能对您更有用。您的谓词可能类似于:
struct unit_predicate {
unit_predicate(const string& s): str(s) {}
bool operator()(const Unit* unit) const {
return unit->isUnit(str);
}
const string& str;
};
UnitCollection::const_iterator unit = std::find_if(units.begin(), units.end(), unit_predicate("Some Unit"));
其他几点意见:
isUnit函数最好按常量引用获取字符串,以避免不必要的副本
你说你想返回一个项目的索引;对于链表来说,这通常是不合理的,因为您无法通过索引获取项目。如果你想通过索引来处理它们,或许std::vector对你更有用。我忘了提这一点,我还是被卡住了。我在find_if中使用什么谓词?该函数位于列表中包含的对象中。这个链接与我理想情况下需要的内容类似,我会使用boost,但我无法确定标准:我忘了提到这一点,我仍然被卡住了。我在find_if中使用什么谓词?该函数位于列表中包含的对象中。这个链接与我理想情况下需要的类似,我会使用boost,但我不能满足以下条件:索引和列表不能同时使用。最好返回迭代器或指针。索引和列表不能同时使用。您最好返回一个迭代器或指针。很遗憾,Boost不可用:@Dominic Bou Samra:然后使用bind2nd、mem\u fun\u ref和friends。@Billy ONeal看到了吗
我上面的最后一段。这些都不起作用,因为mem_-fun生成一元函数,函数的参数是调用函数的对象。mem_fun或其任何朋友都没有生成二进制函数的版本。当然,@Dominic可以做的是创建一个函数对象,该对象可以作为标准算法的独立对象,也可以选择使用中的任何标准适配器。这可能是你最好的方法。很遗憾,Boost不可用:@Dominic Bou Samra:然后使用bind2nd、mem_fun_ref和friends。@Billy ONeal查看我上面的最后一段。这些都不起作用,因为mem_-fun生成一元函数,函数的参数是调用函数的对象。mem_fun或其任何朋友都没有生成二进制函数的版本。当然,@Dominic可以做的是创建一个函数对象,该对象可以作为标准算法的独立对象,也可以选择使用中的任何标准适配器。这可能是你最好的方法。谢谢-这很好用。考虑到我的“做某事”是删除某个项目,我也可以使用可爱的“删除”按钮。是的,索引是愚蠢的,但它是一种满足似乎是最不真实的标准和代码规范的情况,使用他们告诉我们的。@Dominic:你必须使用列表吗?是的:我想使用VectorHanks-这非常有效。考虑到我的“做某事”是删除某个项目,我也可以使用可爱的“删除”按钮。是的,索引是愚蠢的,但它是一种满足似乎是最不真实的标准和代码规范的情况,使用他们告诉我们的。@Dominic:你必须使用列表吗?是的:我想使用向量