问题概述:我使用std :: vector来保存Subject的对象。现在这个向量包含很多对象(有很多我指的是最多10-20个对象)。
这些对象具有字符串成员值,如类别和 sub_category 。
category和sub_category都可以包含字符串,该字符串可以与其他对象的sub_category&类别。
问题:现在我希望我的std :: vector只包含那些的sub_category为唯一的对象。如果类别不是唯一的,则不是问题。
其次,如果我们发现2个对象具有相同的sub_category,那么我们必须从向量中删除其中一个。我们将根据一些规则示例删除它
删除规则如果是
i)主题的实例 - > category =“Land”或者如果category =“Jungle”则删除其他重复的对象,
ii)如果上述条件不匹配,则删除其中任何一个。
我想知道,我如何比较矢量中的子项。例如
我上课说主题
class Subject
{
public :
// some constructors,
// functions to get ., set category and sub category
std::String get_sub_category()
std::string get_category();
private:
std::string category;
std::string sub_category;
}
我有存储主题对象的向量。示例
vector<Subject> sub_vec;
现在我想要的是从具有相同sub_category的向量中删除对象 我不是在寻找源代码,我需要一个起点,? 示例
说
sub_vec[0] = Animal object that has sub_category Tiger
sub_vec [1] = Animal object with Lion as sub category
sub_vec[2] = Forest object with sub_category Tiger
所以我想要的是基于某些条件(我可以做)移除包含Tiger的Forest或Animal对象。 但是为了那个我怎么做比较?
感谢大家的帮助。我已经编写了这个功能并进行了检查,但我确信还有很大的改进余地。请你们解决我的陷阱。
std::vector< Subject >copy_vector; // copy_vector conatins all the objects of SUbject with redundant sub_category
for( std::vector< Subject >::iterator ii = copy_vector.begin() ; ii != copy_vector.end() ; ++ii )
{
sub_category = ii->get_sub_category();
std::cout <<" sub_category-- in main for loop " << sub_category << std::endl ;
std::vector< Subject >::iterator it = ii+1;
while( it != copy_vector.end() )
{
std::cout <<" the size of copy _vector is = " << copy_vector.size() << std::endl ; // for debug purpose
if( it->get_sub_category() == sub_category )
{
std::cout <<" we got a match here" << std::endl ;
// since both are duplicate , we have to delete one of them. Rules for deleting are if
i) instance of Subject ->category = " Land " OR if category = "Jungle" then delete other duplicate object ,
ii) if above condition doesn't match then delete either of them.
if( ( it->get_category == "Land" ) || ( it->get_category == "Jungle" ) )
{
std::cout <<" we are deleting it reference value " << std::endl ;
it = copy_vector.erase(ii);
// increment the counter
++ii;
}
else if( ( ii->get_category == "Land" ) || ( ii->get_category == "Jungle" ) )
{
std::cout <<" we are deleting from copy_vector " << std::endl ;
it = copy_vector.erase(it);
}
else
{
std::cout <<" we are deleting from copy_vector when there is no match for rules " << std::endl ;
it = copy_vector.erase(it);
}
std::cout <<" the size of copy _vector is = " << copy_vector.size() << std::endl ;
}
else
{
std::cout <<" No Match" << std::endl;
// increase main iterator
if( it != copy_vector.end() )
{
++it;
}
}
}
}
//print value
for( std::vector< Subject >::iterator ii = copy_vector.begin() ; ii != copy_vector.end() ; ++ii )
{
std::cout <<" New list = " << ii->get_category <<" \t " << ii->get_sub_category() << std::endl;
}
答案 0 :(得分:1)
一种方法是使用remove_if。要检查对象是否具有重复的sub_category,您可以使用函数或函子来存储它在set或unordered_map中找到的子类别,并删除集合中已存在其sub_category的所有对象/ unordered_map。
注意,unordered_map仅在c ++ 11中可用。
答案 1 :(得分:0)
您应该使用lambda表达式或定义功能对象。
使用lambda表达式
的示例#include <vector>
#include <string>
#include <algorithm>
// ...
std:string tiger = "Tiger";
sub_vec.erase( std::remove_if( sub_vec.begin(), sub_vec.end(),
[&]( const Subject &s ) { return ( s.sub_category == tiger ); } ),
sub_vec.end() );
考虑到上面的代码删除了sub_category等于“Tiger”的所有obexts。如果只需删除重复项,则首先应找到子类别的第一个对象,然后删除具有相同子类别的所有其他对象。在这种情况下,代码可能看起来像
#include <vector>
#include <string>
#include <algorithm>
// ...
std:string tiger = "Tiger";
auto equal_sb_category = [&]( const Subject &s ) { return ( s.sub_category == tiger ); };
auto it = std::find_if( sub_vec.begin(), sub_vec.end(), equal_sb_category );
if ( it != sub_vec.end() )
{
sub_vec.erase( std::remove_if( std::next( it ), sub_vec.end(), equal_sb_category ),
sub_vec.end() );
}
答案 2 :(得分:0)
您可以尝试使用BOOST_FOREACH迭代向量元素
我正在做类似的事情:
BOOST_FOREACH( Subject f, sub_vec )
{
///TODO: do your filtering here
if(f.sub_category == "<bla bla>")
}
我喜欢使用BOOST_FOREACH的原因是它使代码非常易读,当你处理许多向量元素和许多过滤可能性时,那肯定是一个需要考虑的因素
答案 3 :(得分:0)
您的解决方案具有时间复杂度O(n * n),但问题可以通过复杂度O(n * log(n))甚至O(n)来解决。
首先,让我们定义这样的类别比较功能(如果类别是&#34; Land&#34;或&#34; Jungle&#34;那么它比其他类别更大):< / p>
bool CategoryLess(string sCategory1, string sCategory2){
return sCategory1 != "Land" && sCategory1 != "Jungle"
&& (sCategory2 == "Land" || sCategory2 == "Jungle");
}
现在遍历向量并将所有找到的子类别和相应的主题存储在std::unordered_map
(如果您不使用C ++ 11,则为std::map
)。如果子类别已在map
中,则替换相应的Subject
,如果已找到Subject
的类别少于新Subject
的类别:
unordered_map<string, Subject*> Subcategories;
for (int i=0; i<sub_vec.size(); ++i){
unordered_map<string, Subject*>::iterator
it = Subcategories.find(sub_vec[i].get_sub_category());
if (it != Subcategories.end()){
if (CategoryLess((*it)->get_category(), sub_vec[i].get_category())
it->second = &sub_vec[i];
}
else
Subcategories[sub_vec[i].get_sub_category()] = &sub_vec[i];
}
现在您拥有所有子类别和相应Subject
的地图
如果我们发现两个或多个Subject
具有相同的子类别,则地图包含指向具有更大类别的Subject
的指针。
现在再次迭代sub_vec并删除Subject
,如果
Subcategories[sub_vec[i].get_sub_category()] != &sub_vec[i];
时间复杂度:
如果我们使用std::unordered_map
,则两个周期的预期时间复杂度为O(n)(在最坏的情况下为O(n * n))。
如果我们使用std::map
,则两个周期的时间复杂度为O(n * log(n))。
(我没有考虑字符串比较的时间复杂性和vector.erase无关紧要)
请注意,而不是从向量中删除Subject
时,可以更改其他Subject
的地址。因此,在将指向Subject
的指针(例如,复制需要Subject
s)与另一个向量进行比较而不是从向量中删除其他Subject
时,需要注意。但它并没有改变我的解决方案的总体思路。