我有一个像这样的boost multi_index容器:
typedef multi_index_container<
MyData,
indexed_by<
random_access<>, // keep insertion order
ordered_non_unique< member<MyData, time_t, &MyData::timestamp> >
>
> myContType;
typedef myContType::nth_index<1>::type myContType_by_time;
和搜索方法:
unsigned long searchByTimestamp(time_t timestamp)
{
myContType_by_time& idIndex = myCont.get<1>();
myContType_by_time::iterator itTime = idIndex.find(timestamp);
if (itTime == idIndex.end())
return 0;
// change the index from timestamp to insertionoder(id)
myContType::const_iterator itId = myCont.project<0>(itTime);
return itTime->id;
}
我使用timestamp(
get<1> index
)进行搜索,并且它起作用了,但是它从第一个(最早的)数据开始搜索。我想根据插入顺序(get<0> index
)从最后添加的(最新)数据开始执行此操作。我尝试了该代码,但是没有用。myCont.rearrange(get<0>(myCont).rbegin());
第一个问题:是否有一种方法可以从最后输入的数据开始搜索(根据插入顺序而不是时间戳,我的意思是get 索引)
第二个问题:如果找到的数据不是我想要的数据,如何从当前位置/索引继续搜索?我的意思是有没有像find_next这样的方法? (我在文档中找不到)
我正在使用Boost版本1.47.0开发Visual Studio 2008。
谢谢。
最佳答案
您可能应该只使用std::find
中的<algorithm>
,以及第一个索引中的反向迭代器:
unsigned long searchByTimestamp(Time_t timestamp)
{
auto& idIndex = myCont.get<0>();
auto itTime = std::find_if(
idIndex.rbegin(), idIndex.rend(),
[=](MyData const& item) { return item.timestamp == timestamp; }
);
if (itTime == idIndex.rend())
return 0;
return itTime->id;
}
注意:如果要将反向迭代器“投影”到(正向)迭代器,请在反向迭代器上使用
.base()
。看到它 Live On Coliru
现在,我真的不知道您需要
continue searching from the "current" position
的功能是什么(我的意思是,找到返回匹配项或rend()
的内容,因此就没有继续了)。但是,否则,您可以做类似的事情(也可以查看 Live On Coliru :)unsigned long searchByTimestamp(Time_t timestamp)
{
auto& idIndex = myCont.get<0>();
auto current = std::find_if(idIndex.rbegin(), idIndex.rend(),
[=](MyData const& item) { return item.timestamp >= timestamp; });
if (current != idIndex.rend())
{
bool some_extra_condition = current->timestamp == timestamp; // exact match?
if (some_extra_condition)
return current->id; // we have an exact match
} else
{
// otherwise look for the next item that has an id divisible by 3 (3,6,9,...)
auto alternative = std::find_if(current, idIndex.rend(),
[=](MyData const& item) { return (item.id % 3) == 0; });
if (alternative != idIndex.rend())
return alternative->id;
}
return 0;
}
我完全构成了“替代”匹配谓词的愚蠢示例。如您所见,这都是常规STL算法的用法。这是可能的,因为算法是通过迭代器与容器分离的。
完整代码
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
using namespace boost::multi_index;
static int idgen = 0;
enum Time_t { last_month, last_week, yesterday, today, tomorrow };
std::ostream& operator<<(std::ostream& os, Time_t tt) {
switch(tt)
{
case last_month: return os << "last_month";
case last_week: return os << "last_week";
case yesterday: return os << "yesterday";
case today: return os << "today";
case tomorrow: return os << "tomorrow";
default: return os << "?";
};
}
struct MyData
{
int id = ++idgen;
MyData(Time_t timestamp) : timestamp(timestamp) {}
Time_t timestamp;
friend std::ostream& operator<<(std::ostream& os, MyData const& md)
{
return os << "(id:" << md.id << ", timestamp:" << md.timestamp << ")";
}
};
typedef multi_index_container<
MyData,
indexed_by<
random_access<>, // keep insertion order
ordered_non_unique< member<MyData, Time_t, &MyData::timestamp> >
>
> myContType;
typedef myContType::nth_index<1>::type myContType_by_time;
myContType myCont;
unsigned long searchByTimestamp(Time_t timestamp)
{
auto& idIndex = myCont.get<0>();
auto itTime = std::find_if(
idIndex.rbegin(), idIndex.rend(),
[=](MyData const& item) { return item.timestamp == timestamp; }
);
if (itTime == idIndex.rend())
return 0;
return itTime->id;
}
#include <iostream>
int main()
{
myCont.emplace_back(Time_t(last_week));
myCont.emplace_back(Time_t(tomorrow));
myCont.emplace_back(Time_t(last_month));
myCont.emplace_back(Time_t(yesterday));
std::cout << "Insertion order:\n";
for (auto const& item : myCont)
std::cout << item << "\n";
std::cout << searchByTimestamp(today) << "\n";
std::cout << searchByTimestamp(last_month) << "\n";
}
关于c++ - 反向搜索和Multi_Index容器中的find_next函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21677550/