我有以下数据:
FolioA Name1 100
FolioA Name2 110
FolioA Name3 100
FolioB Name1 100
FolioB Name3 106
FolioC Name1 108
FolioC Name2 102
FolioC Name3 110
我想只插入唯一的名称(即Name1,Name2和Name3,每一次)到
std::vector<std::string> name;
当我遍历数据时。
所以,我有以下代码,我将数据存储在一个名为test的地图中:
std::map<std::string, std::map<std::string, double> >test;
std::map<std::string, std::map<std::string, double > >::iterator it1 = test.begin(), end1 = test.end();
while (it1 !=end1) {
std::map<std::string, double>::iterator it2 = it1->second.begin(), end2=it1->second.end();
**name.push_back(it2->first);**
++it2;
}
++it1;
}
但是,目前通过按照我的方式将数据推送到名称中的Name1,Name2的2个实例和Name3的3个实例,这是我的代码所期望的。如何修复它只有唯一的名称。
答案 0 :(得分:29)
由于您希望保留给定名称的第一个实例,因此您必须在某个时刻执行名称查找。仅涉及向量的简单算法可以使用std::find
检查条目是否已存在std::vector<std::string> name;
....
if (std::find(name.begin(), name.end(), someName) == name.end()) {
// someName not in name, add it
name.push_back(someName);
}
但是,每次要插入元素时,您都会执行搜索,而这(单独)最多可达O(N)
复杂度,为整个算法提供O(N*N)
。因此,您可以使用快速查找的中间容器进行优化,例如@Chad建议的std::set
,查找的复杂度为O(logN)
,总体上为O(N*logN)
,或者一个哈希容器,如C ++ 11的std::unordered_set,它具有接近恒定的时间查找,给出了~O(N)的整体复杂性。
std::unordered_set name_set;
....
// still need to search, since you want to keep
// the first instance of each name, and not the last.
// But unordered_set performs the look-up at insertion,
// only inserting if someName not already in the set
name_set.insert(someName);
然后,按照@Chad的例子,
std::vector<std::string> name(names_set.begin(), name_set.end());
如果您没有C ++ 11,则哈希映射替代方案为boost::hash_map
和tr1::hash_map
。
答案 1 :(得分:2)
如果您不关心要在数据结构中输入哪个实例,std::set将为您的目的服务
答案 2 :(得分:2)
也许您应该使用另一张地图而不是矢量来拥有唯一的名称。
std :: map&lt; std :: string,double&gt;名;
答案 3 :(得分:2)
您要求提供示例代码,以下是我将如何做到这一点:
std::set<std::string> unique_names;
// ...
while (it1 !=end1)
{
// ...
// **name.push_back(it2->first);**
unique_names.insert(it2->first);
}
std::vector<std::string> name(unique_names.begin(), unique_names.end());
答案 4 :(得分:1)
list具有.sort()和.unique()的能力,它将为您提供。
你可以用迭代器迭代它并用initializer_list初始化它。
数据实际上看起来更像是我的结构:
#include <iterator>
#include <list>
#include <string>
#include <fstream>
typedef struct NODE_S {
string name1, name2;
int n;
} NODE_S NODE;
bool compare_NODE (NODE first, NODE second)
{
unsigned int i=0;
if (first.name1 < second.name1) {
return true;
} else if (first.name2 < second.name2) {
return true;
} else if (first.n < second.n) {
return true;
} else { return false;}
}
bool readfile(list<NODE>& ln, string filepath) {
std::ifstream filein;
NODE n;
filein.open(filepath.c_str(), std::iofstream::in);
if (!filein.good()) {
filein.close();
std::cerr << "ERROR: unable to open file \"" << filepath << "\" or file is zero-length." << std::endl;
return false;
}
do {
filein >> n.name1 >> n.name2 >> n.name3 >> std::skipws;
ln.push_back(n);
ln.sort(compare_NODE);
ln.unique();
//add node to list
} while (!filein.good()); //can use .eof here, but if bad disk blocks...
filein.close();
return true;
}
int main(int argc, char * argv[], char * envp[]) {
string filepath="somefile.txt";
if (!readfile(filepath)) {
return 1;
}
list<NODE>::iterator lni;
for (lni = ln.begin(); lni != ln.end(); lni++) {
std::cout<<lni->name1<<' '<<lni->name2<<' '<<lni->n<<std::endl;
}
return 0;
}