我必须开发一个组件 将有一个以上 100,000个类的实例。和我 想要基于的生成报告 不同的标准(成员) 特定班级。例如, 具有数据字段ID的员工类, 名字,地址,phoneno。报告 一代将基于
每次调用的实例的运行时迭代非常慢,因为它是对大量实例的线性操作,需要排序机制。
所以我以不同的排序方式在容器中存储了每个实例的指针。但是需要更多的内存。请建议我这样做的更好方法。我已经发布了我遵循的示例代码片段以实现上述目标。
class Employee
{
int m_id;
string m_name;
string m_addr;
string m_phone;
public:
Employee(int id, string name, string addr, string phone) :
m_id(id), m_name(name), m_addr(addr), m_phone(phone) { }
int id() const { return m_id; }
string name() const { return m_name; }
string addr() const { return m_addr; }
string phoneno() const { return m_phone; }
};
//custom predicate for std containers
struct IDComparator
{
bool operator() (const Employee* e1, const Employee* e2 )
{
return e1->id() < e2->id();
}
};
struct NameComparator
{
bool operator() (const Employee* e1, const Employee* e2 )
{
return e1->name() < e2->name();
}
}
struct AddressComparator
{
bool operator() (const Employee* e1, const Employee* e2 )
{
return e1->addr() < e2->addr();
}
};
struct PhoneComparator
{
bool operator() (const Employee* e1, const Employee* e2 )
{
return e1->phoneno() < e2->phoneno();
}
};
//Class which holds huge number of employee instances
class Dept
{
private:
typedef set<Employee*, IDComparator> EMPID; //unnique id
typedef EMPID::iterator EMPID_ITER;
typedef multiset<const Employee*, NameComparator> EMPNAME; // for sorted names
typedef EMPNAME::iterator NAME_ITER;
typedef multiset<const Employee*, AddressComparator> EMPADDR; // for sorted addr
typedef EMPADDR::iterator ADDR_ITER;
typedef multiset<const Employee*, PhoneComparator> EMPPHONE; // for sorted phoneno
typedef EMPPHONE::iterator PHONE_ITER;
private:
EMPID m_empids;
EMPNAME m_names ;
EMPADDR m_addr;
EMPPHONE m_phoneno;
public:
Dept() { }
~Dept() { //delete the instances of employees }
void add(Employee* e)
{
EMP_ITER iter = m_empids.insert(e).first;
const Employee* empptr = &*iter;
m_names.insert(empptr); // adds employee pointer to name multimap
m_addr.insert(empptr); // adds employee pointer to addr multimap
m_phoneno.insert(empptr); // adds employee pointer to phone multimap
}
void print_emp_dtls() const; //prints all the emp dtls iterating though EMPID
void print_unique_names() const; //iterate EMPNAME & use upperbound & lowerbound, prints unique names
void print_asc_name() const; //iterate EMPNAME & prints all names in ascending order
void print_desc_name() const; //back iterate EMPNAME & prints all names in descending order
void print_unique_adrr() const; //iterate EMPADDR & use upperbound & lowerbound, prints unique address
void print_asc_addr() const; //iterate EMPADDR & prints all addr in ascending order
void print_desc_addr() const; //back iterate EMPADDR & prints all address in descending order
void print_unique_phoneno() const; //iterate EMPPHONE & use upperbound & lowerbound,prints unique phoneno
void print_asc_phoneno() const; //iterate EMPPHONE & prints all phoneno in ascending order
void print_desc_phoneno() const; //back iterate EMPPHONE & prints all phoneno in };
答案 0 :(得分:5)
似乎是Boost.MultiIndex的完美候选人:
Boost多指数容器 库提供了一个类模板 名为multi_index_container的 能够构建容器 保持一个或多个指数 不同的排序和访问 语义强>
答案 1 :(得分:3)
我过去成功使用过Boost.Multi_index。你可能会从第一眼看到它很奇怪,但实际上它是退出有趣的库。在使用它时请记住,您没有在自定义容器中提供“如何”而是“什么”。假设您有以下类型:
struct user_t
{
string id, name, email;
int age;
friend ostream& operator<<(ostream& output_stream, const user_t& user)
{
return output_stream
<< user.id << " "
<< user.name << " "
<< user.age << " "
<< user.email << "\n";
}
friend istream& operator>>(istream& input_stream, user_t& user)
{
return input_stream >> user.id >> user.name >> user.age >> user.email;
}
};
您将创建一个容器,它可以保存对象和任意数量的索引。在我们开始之前,我们定义索引的标签。标签只是标签!您用来通过名称而不是神奇的数字来访问索引:
struct by_id { };
struct by_name { };
struct by_age { };
struct by_email { };
然后我们用所需的索引定义我们的“数据库”:
typedef multi_index_container<
user_t,
indexed_by
<
ordered_unique<tag<by_id>, member<user_t, string, &user_t::id> >,
ordered_non_unique<tag<by_name>, member<user_t, string, &user_t::name> >,
ordered_non_unique<tag<by_age>, member<user_t, int, &user_t::age> >,
ordered_non_unique<tag<by_email>, member<user_t, string, &user_t::email> >
>
> user_db;
首先是容器中的元素类型。然后,您说我想通过以下内容索引此容器:
indexed_by
<
ordered_unique<tag<by_id>, member<user_t, string, &user_t::id> >,
ordered_non_unique<tag<by_name>, member<user_t, string, &user_t::name> >,
ordered_non_unique<tag<by_age>, member<user_t, int, &user_t::age> >,
ordered_non_unique<tag<by_email>, member<user_t, string, &user_t::email> >
>
您只需指定要公开的索引类型。实际上有各种类型,它取决于您拥有的数据的语义。最好为每个索引(第一个参数)指定一个标记,并指定要通过第二个模板参数索引类型。实际上有多种方法可以选择数据的“关键”。密钥实际上不需要是唯一的!
从现在开始,您只需像常规std::multi_set
一样处理user_db!实际上差别很小;)让我们说你想从文件中加载系列化用户的信息,并根据我们创建的不足重新定位有序信息:
user_db load_information()
{
ifstream info_file("information.txt");
user_db db;
user_t user;
while(info_file >> user)
db.insert(user);
return db;
}
template <typename index_t>
void save_information_by(ostream& output_stream, const index_t& index)
{
ostream_iterator<user_t> serializer(output_stream);
copy(index.begin(), index.end(), serializer);
}
int main()
{
ofstream
by_id_file("by_id.txt"),
by_name_file("by_name.txt"),
by_age_file("by_age.txt"),
by_email_file("by_email.txt");
user_db db = load_information();
// You see why we created the tags,
// if we didn't we had to specify the index like the following:
// const auto& name_index = db.get<by_name>(); ==
// const auto& name_index = db.get<1>();
const auto& id_index = db.get<by_id>();
const auto& name_index = db.get<by_name>();
const auto& age_index = db.get<by_age>();
const auto& email_index = db.get<by_email>();
save_information_by(by_id_file, id_index);
save_information_by(by_name_file, name_index);
save_information_by(by_age_file, age_index);
save_information_by(by_email_file, email_index);
}
答案 2 :(得分:2)
查看boost::multi_index
here。有一个容器boost::multi_index_contaier
,允许您使用各种键搜索项目。