查找两个字符串向量的交集
Posted
技术标签:
【中文标题】查找两个字符串向量的交集【英文标题】:Finding the intersection of two vectors of strings 【发布时间】:2013-02-04 13:58:59 【问题描述】:我有两个字符串向量,想找到两个字符串中都存在的字符串,用公共元素填充第三个向量。编辑:我已经添加了带有相应输出的完整代码清单,以便清楚。
std::cout << "size " << m_HLTMap->size() << std::endl;
/// Vector to store the wanted, present and found triggers
std::vector<std::string> wantedTriggers;
wantedTriggers.push_back("L2_xe25");
wantedTriggers.push_back("L2_vtxbeamspot_FSTracks_L2Star_A");
std::vector<std::string> allTriggers;
// Push all the trigger names to a vector
std::map<std::string, int>::iterator itr = m_HLTMap->begin();
std::map<std::string, int>::iterator itrLast = m_HLTMap->end();
for(;itr!=itrLast;++itr)
allTriggers.push_back((*itr).first);
; // End itr
/// Sort the list of trigger names and find the intersection
/// Build a typdef to make things clearer
std::vector<std::string>::iterator wFirst = wantedTriggers.begin();
std::vector<std::string>::iterator wLast = wantedTriggers.end();
std::vector<std::string>::iterator aFirst = allTriggers.begin();
std::vector<std::string>::iterator aLast = allTriggers.end();
std::vector<std::string> foundTriggers;
for(;aFirst!=aLast;++aFirst)
std::cout << "Found:" << (*aFirst) << std::endl;
;
std::vector<std::string>::iterator it;
std::sort(wFirst, wLast);
std::sort(aFirst, aLast);
std::set_intersection(wFirst, wLast, aFirst, aLast, back_inserter(foundTriggers));
std::cout << "Found this many triggers: " << foundTriggers.size() << std::endl;
for(it=foundTriggers.begin();it!=foundTriggers.end();++it)
std::cout << "Found in both" << (*it) << std::endl;
; // End for intersection
然后是输出
这是部分输出,向量中有超过 1000 个元素,所以我没有包含完整输出:
Found:L2_te1400
Found:L2_te1600
Found:L2_te600
Found:L2_trk16_Central_Tau_IDCalib
Found:L2_trk16_Fwd_Tau_IDCalib
Found:L2_trk29_Central_Tau_IDCalib
Found:L2_trk29_Fwd_Tau_IDCalib
Found:L2_trk9_Central_Tau_IDCalib
Found:L2_trk9_Fwd_Tau_IDCalib
Found:L2_vtxbeamspot_FSTracks_L2Star_A
Found:L2_vtxbeamspot_FSTracks_L2Star_B
Found:L2_vtxbeamspot_activeTE_L2Star_A_peb
Found:L2_vtxbeamspot_activeTE_L2Star_B_peb
Found:L2_vtxbeamspot_allTE_L2Star_A_peb
Found:L2_vtxbeamspot_allTE_L2Star_B_peb
Found:L2_xe25
Found:L2_xe35
Found:L2_xe40
Found:L2_xe45
Found:L2_xe45T
Found:L2_xe55
Found:L2_xe55T
Found:L2_xe55_LArNoiseBurst
Found:L2_xe65
Found:L2_xe65_tight
Found:L2_xe75
Found:L2_xe90
Found:L2_xe90_tight
Found:L2_xe_NoCut_allL1
Found:L2_xs15
Found:L2_xs30
Found:L2_xs45
Found:L2_xs50
Found:L2_xs60
Found:L2_xs65
Found:L2_zerobias_NoAlg
Found:L2_zerobias_Overlay_NoAlg
Found this many triggers: 0
可能的原因
我开始认为我编译代码的方式应该受到指责。我目前正在使用 ROOT(物理数据分析框架)进行编译,而不是进行独立编译。我觉得它不能很好地与 STL 算法库一起工作,这就是问题的原因,特别是考虑到有多少人似乎有代码为他们工作。我会尝试做一个独立的编译并重新运行。
【问题讨论】:
您的allTriggers
似乎是空的,所以我希望交叉点也是空的。还是你无论如何都要把它填满?
如果您查看示例中的示例,例如this reference page 对于std::set_intersection
,您会看到目标集合已创建empty,std::back_inserter
用于插入目标。你试过吗?
@JoachimPileborg 我见过的大多数示例都预先分配了目标向量,然后使用了我拥有的语法。我现在将 back_inserter。
@JacoboBlanco:你能展示一下你是如何填写allTriggers
的吗?我试图将wantedTriggers
的第一个元素推入allTriggers
并且交集行为正常
【参考方案1】:
传递foundTriggers.begin()
,foundTriggers
为空,因为输出参数不会导致输出被推送到foundTriggers
。相反,它会将迭代器递增到向量的末尾而不调整其大小,从而随机破坏内存。
您想使用插入迭代器:
std::set_intersection(wFirst, wLast, aFirst, aLast,
std::back_inserter(foundTriggers));
更新:正如 cmets 中所指出的,向量的大小已调整为至少足够大以获得结果,因此您的代码应该可以工作。请注意,您应该使用从 set_intersection
返回的迭代器来指示交集的结束 - 您的代码会忽略它,因此您还将遍历输出末尾留下的空字符串。
您能否发布一个完整的测试用例,以便我们可以查看交集是否实际上是空的?
【讨论】:
但他确实初始化了foundTriggers
以包含适当数量的元素,所以它应该可以工作
我发现了一些预先分配了目标向量的示例,然后只使用了 destinatio.begin()。我现在就试试这个。
@AndyProwl set_intersection
如何知道何时停止递增输出迭代器?它不能,所以当交叉点大于它的大小时,它就会从foundTriggers
的末端跑出。
@AndyProwl:他做到了。当时没有发布的代码可能有问题。
@jrok:调用者只需要确保目标范围足够大。这就是为什么如果你的目标集合是空的,你必须使用back_inserter
【参考方案2】:
你的allTrigers
向量是毕竟是空的。填充时,您永远不会将 itr
重置为地图的开头。
编辑:
其实你从来没有重置过aFirst
:
for(;aFirst!=aLast;++aFirst)
std::cout << "Found:" << (*aFirst) << std::endl;
;
// here aFirst == aLast
std::vector<std::string>::iterator it;
std::sort(wFirst, wLast);
std::sort(aFirst, aLast); // **** sorting empty range ****
std::set_intersection(wFirst, wLast, aFirst, aLast, back_inserter(foundTrigger));
// ^^^^^^^^^^^^^^
// ***** empty range *****
我希望您现在能明白为什么缩小变量范围是一种好习惯。
【讨论】:
对不起,我只是在调试时添加了它,但在发布之前从未运行过它,我最诚挚的道歉。矢量已正确填充。【参考方案3】:您永远不会使用set_intersection
的返回值。在这种情况下,您可以在set_intersection
返回后使用它来调整foundIterators
的大小,或者作为for 循环的上限。否则,您的代码似乎可以工作。请问可以看一下完整的可编译程序及其实际输出吗?
【讨论】:
我已经包含了输出,问题是我使用了一些 ROOT 库和一个 ROOT 数据文件作为我的 m_HLTNameMap 源,所以我无法提供完全可编译的源。 我将首先解决我提到的问题,因为它可能会给您带来一些困惑。报告为“找到这么多触发器:”的数字将是您在构建时给 foundTriggers 的大小。顺便说一句,您的代码示例仍然无法按原样编译 - 例如,未声明 aFirst。 我的错误,aFirst 已声明,您已使用 back_inserter 解决了问题。自从我上次查看以来,我没有注意到代码发生了多大的变化。 jrok 有当前问题的答案。以上是关于查找两个字符串向量的交集的主要内容,如果未能解决你的问题,请参考以下文章
R语言常用函数:交集intersect并集union找不同setdiff判断相同setequal的运用