Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;多对多地图_C++ - Fatal编程技术网

C++ C++;多对多地图

C++ C++;多对多地图,c++,C++,我需要一个数据结构来存储这些信息,以便:(我有多对多) 1.如果有员工,我可以找到项目 2.考虑到项目,我可以找到员工 如果我使用多地图,那么我需要维护2张地图, 这里还有其他数据结构可以使用吗 > P>你可以使用两个映射,也可以使用.< /P> < P>我不知道在标准C++中有任何预先打包的数据结构。在我看来,您需要两种数据结构,其形式如下: std::map<unsigned long,std::vector<unsigned long> > employee_pro

我需要一个数据结构来存储这些信息,以便:(我有多对多)

1.如果有员工,我可以找到项目 2.考虑到项目,我可以找到员工

如果我使用多地图,那么我需要维护2张地图,
这里还有其他数据结构可以使用吗

> P>你可以使用两个映射,也可以使用.< /P> < P>我不知道在标准C++中有任何预先打包的数据结构。在我看来,您需要两种数据结构,其形式如下:

std::map<unsigned long,std::vector<unsigned long> > employee_projects
std::映射员工项目
其中一个是:

std::map<unsigned long,std::vector<unsigned long> > project_employees
std::映射项目员工
其中employee_projects是映射到projectd列表的整数(employeeid)列表,而project_employees则是相反的。预先填充这两个,您可以在整个应用程序中快速引用它们


警告:运行期间的任何修改都必须手动应用于每个结构。

选择您认为最常见的关系并创建映射。然后,编写函数或从map类派生,并使用方法进行扩展,以便在另一个方向执行查找。这种查找显然要慢得多(必须迭代这些值),但它可以让您只使用一个映射


如果你意识到你需要更多地查找另一个地图,或者你想切换到使用2个地图或其他解决方案,那么最好将整个事情包装在一个类中,这样你就可以更改地图。

你可以按照你的建议使用两个大的全局ish多重地图,也可以在项目和员工数据结构中本地维护信息。让Project类包含指向Employee的指针向量(或集合),Employee类包含指向Project的指针向量/集合,以及一个函数,该函数通过将指向每个员工的指针推到另一个员工的向量上,将员工与项目相关联。然后,给定其中一个对象,可以获得与之关联的其他类型的对象的集合。比如:

    (in Employee.h):
class Project;  // Forward declare project

class Employee {
public:
  AddProject(Project *proj);
  vector<Project *> projects();
  size_t num_projects() {return projects_.size();}
  Project *project(size_t i) {return projects_[i];}
private:
  vector<Project *> projects_;
};
(在Employee.h中):
类项目;//远期申报项目
班级员工{
公众:
添加项目(项目*项目);
向量项目();
size_t num_projects(){return projects.size();}
项目*项目(大小){返回项目}
私人:
矢量工程;
};
同样的,对于Project.h

任何一种方法都可以奏效;本地方法是在没有可用的multimap的语言(如C)中通常采用的方法。您还可以使用索引或ID代替指针。本地方法的一个优点是,您需要对项目和员工进行的更多工作可以成为项目/员工类的本地行为,使用这些类的方法实现,并与系统的其余部分分开进行单元测试。这不适用于多重映射方法,因为单个类对多重映射一无所知

这里的区别不是很明显,这里只有两个类,但我见过很多这样的关系用大型全局ish数据结构表示,这些数据结构是大型monster类的一部分,单元测试几乎不可能(因为您需要在monster类中设置如此多的数据结构才能完成任何事情)。

您可以使用

您可以按如下方式定义容器:

struct Connection
{
   Employee emp;
   Project  prj;
};

typedef multi_index_container
<
    Connection,
    indexed_by
    <
        ordered_unique< identity<Connection> >,
        ordered_non_unique< member<Connection, Employee, &Connection::emp> >,
        ordered_non_unique< member<Connection, Project, &Connection::prj> >
    >
> Relation;

+1,我想说在一个新类上包装两个映射,但是Bimap已经解决了这个问题,很好的发现。但是这不允许多对多关系,是吗?在我看来,在Bimap中,键必须是唯一的,两边都是,这样只能处理一对一的关系。(很抱歉挖出来了…)
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>

#include <iostream>
#include <string>
#include <functional>

namespace mi = boost::multi_index;

// these two type should implement std::less or operator<
typedef std::string Employee; // change to your definition
typedef std::string Project;  // change to your definition

struct Connection
{
   Employee emp;
   Project  prj;

   Connection(const Employee& e, const Project& p): emp(e), prj(p) {}
   bool operator <(const Connection& rhs) const
   {
      return std::less<Employee>()(emp, rhs.emp) ||
             ( emp == rhs.emp && std::less<Project>()(prj, rhs.prj) );
   }
};

struct employee {}; // for tag
struct project  {}; // for tag

typedef mi::multi_index_container
<
    Connection,
    mi::indexed_by
    <
        mi::ordered_unique
        <
            mi::identity<Connection>
        >,
        mi::ordered_non_unique
        <
            mi::tag<employee>,
            mi::member<Connection, Employee, &Connection::emp>
        >,
        mi::ordered_non_unique
        <
            mi::tag<project>,
            mi::member<Connection, Project, &Connection::prj>
        >
    >
> Relation;

typedef Relation::index_iterator<employee>::type EmpIter;
typedef Relation::index_iterator<project>::type  PrjIter;

int main()
{
    Relation rel;

    rel.insert(Connection("Tom",   "sleeping"));
    rel.insert(Connection("Jerry", "sleeping"));
    rel.insert(Connection("Spike", "sleeping"));
    rel.insert(Connection("Tom",   "tormenting-partner"));
    rel.insert(Connection("Jerry", "tormenting-partner"));
    rel.insert(Connection("Spike", "playing-with-tyke"));
    rel.insert(Connection("Tom",   "fishing"));
    rel.insert(Connection("Jerry", "playing-with-nibbles"));
    rel.insert(Connection("Jerry", "tormenting-partner")); // duplicated

    std::cout << "total connections: " << rel.size() << std::endl;

    std::cout << "employees connected with sleeping project:" << std::endl;
    std::pair<PrjIter, PrjIter> pit = rel.get<project>().equal_range("sleeping");
    for (PrjIter it = pit.first; it != pit.second; ++it)
        std::cout << '\t' << it->emp << std::endl;

    std::cout << "projects connected with Jerry:" << std::endl;
    std::pair<EmpIter, EmpIter> eit = rel.get<employee>().equal_range("Jerry");
    for (EmpIter it = eit.first; it != eit.second; ++it)
        std::cout << '\t' << it->prj << std::endl;

    return 0;
}
total connections: 8
employees connected with sleeping project:
        Tom
        Jerry
        Spike
projects connected with Jerry:
        sleeping
        tormenting-partner
        playing-with-nibbles