2014-07-21 28 views
1

使用Boost網站上提供的示例:http://www.boost.org/doc/libs/1_55_0/libs/multi_index/example/basic.cpp我學會了如何使用迭代器通過索引獲取元素。但是,我想要通過一個索引匹配所有匹配,並按另一個索引排序。查找所有排序在Boost

例如,在給定的例子中,我希望得到名字爲「John」的所有員工,但是結果會按年齡順序返回給我。到目前爲止,當我通過名字得到的時候,我返回到第一次出現「約翰」的迭代器,等等,但是除了插入記錄的順序之外,沒有關於它們被返回的方式的順序。

請幫忙!

培訓相關代碼:

/* Boost.MultiIndex basic example. 
* 
* Copyright 2003-2008 Joaquin M Lopez Munoz. 
* Distributed under the Boost Software License, Version 1.0. 
* (See accompanying file LICENSE_1_0.txt or copy at 
* http://www.boost.org/LICENSE_1_0.txt) 
* 
* See http://www.boost.org/libs/multi_index for library home page. 
*/ 

#if !defined(NDEBUG) 
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING 
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE 
#endif 

#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/member.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <algorithm> 
#include <iostream> 
#include <iterator> 
#include <string> 

using boost::multi_index_container; 
using namespace boost::multi_index; 

/* an employee record holds its ID, name and age */ 

struct employee 
{ 
    int   id; 
    std::string name; 
    int   age; 

    employee(int id_,std::string name_,int age_):id(id_),name(name_),age(age_){} 

    friend std::ostream& operator<<(std::ostream& os,const employee& e) 
    { 
    os<<e.id<<" "<<e.name<<" "<<e.age<<std::endl; 
    return os; 
    } 
}; 

/* tags for accessing the corresponding indices of employee_set */ 

struct id{}; 
struct name{}; 
struct age{}; 

/* see Compiler specifics: Use of member_offset for info on 
* BOOST_MULTI_INDEX_MEMBER 
*/ 

/* Define a multi_index_container of employees with following indices: 
* - a unique index sorted by employee::int, 
* - a non-unique index sorted by employee::name, 
* - a non-unique index sorted by employee::age. 
*/ 

typedef multi_index_container< 
    employee, 
    indexed_by< 
    ordered_unique< 
     tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>, 
    ordered_non_unique< 
     tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>, 
    ordered_non_unique< 
     tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> > 
> employee_set; 

template<typename Tag,typename MultiIndexContainer> 
void print_out_by(
const MultiIndexContainer& s, 
Tag* =0 /* fixes a MSVC++ 6.0 bug with implicit template function parms */ 
) 
{ 
    /* obtain a reference to the index tagged by Tag */ 

    const typename boost::multi_index::index<MultiIndexContainer,Tag>::type& i= 
    get<Tag>(s); 

    typedef typename MultiIndexContainer::value_type value_type; 

    /* dump the elements of the index to cout */ 

    std::copy(i.begin(),i.end(),std::ostream_iterator<value_type>(std::cout)); 
} 


int main() 
{ 
    employee_set es; 

    es.insert(employee(0,"Joe",31)); 
    es.insert(employee(1,"Robert",27)); 
    es.insert(employee(2,"John",40)); 

    /* next insertion will fail, as there is an employee with 
    * the same ID 
    */ 

    es.insert(employee(2,"Aristotle",2387)); 

    es.insert(employee(3,"Albert",20)); 
    es.insert(employee(4,"John",57)); 

    /* list the employees sorted by ID, name and age */ 

    std::cout<<"by ID"<<std::endl; 
    print_out_by<id>(es); 
    std::cout<<std::endl; 

    std::cout<<"by name"<<std::endl; 
    print_out_by<name>(es); 
    std::cout<<std::endl; 

    std::cout<<"by age"<<std::endl; 
    print_out_by<age>(es); 
    std::cout<<std::endl; 

    return 0; 
} 
+0

1.在此處發佈相關代碼,而不是在第三方網站上。 2.您的鏈接已損壞。 – CoryKramer

+0

你可以不使用copy_if來提升 –

+0

是的,但是boost已經到位並且效率更高,所以我想堅持這一點。 – user3853278

回答

1

你可以做到這一點在以下兩種方法之一:

1:基於(姓名,年齡)一個composite key指數更換第二個指標:

typedef multi_index_container< 
    employee, 
    indexed_by< 
    ordered_unique< 
     tag<id>, member<employee,int,&employee::id>>, 
    ordered_non_unique< 
     tag<name>, 
     composite_key< 
     employee, 
     member<employee,std::string,&employee::name>, 
     member<employee,int,&employee::age> 
     > 
    >, 
    ordered_non_unique< 
     tag<age>, member<employee,int,&employee::age>> 
    > 
> employee_set; 

int main() 
{ 
    employee_set es={ 
    {0,"John",31},{1,"Robert",27},{2,"John",57}, 
    {5,"John",2387},{3,"Albert",20},{4,"John",40}}; 

    for(auto p=es.get<name>().equal_range("John");p.first!=p.second;++p.first){ 
    std::cout<<*(p.first); 
    } 
} 

2:顯示結果:

template<typename Iterator> 
std::vector<std::reference_wrapper<const employee>> 
sort_by_age(std::pair<Iterator,Iterator> p) 
{ 
    std::vector<std::reference_wrapper<const employee>> v(p.first,p.second); 
    std::sort(v.begin(),v.end(), 
    [](const employee& e1,const employee& e2){return e1.age<e2.age;}); 
    return v; 
} 

int main() 
{ 
    employee_set es={ 
    {0,"John",31},{1,"Robert",27},{2,"John",57}, 
    {5,"John",2387},{3,"Albert",20},{4,"John",40}}; 

    for(auto e:sort_by_age(es.get<name>().equal_range("John"))){ 
    std::cout<<e; 
    } 
} 

哪個更好? #1在沒有進一步後處理的情況下給出了期望的結果,但是插入到索引中的(稍微)較慢,因爲比較標準比名稱的簡單比較更昂貴。 #2有後處理懲罰,但可以與年齡以外的排序標準一起使用(使用#1,其中一個是第二個鍵在定義時間固定)。

+0

第一種方式絕對是我在尋找的;即使經濟放緩,似乎也是最好的Boost可以做到的。謝謝! – user3853278