如何使用ordered_non_unique索引保持有序
How can I preserve sequenced order with an ordered_non_unique index?
我有一个boost::multi_index_container,由ordered_non_unique键索引,并排序。当对非唯一索引进行迭代时,会按照添加到容器中的顺序而不是它们在序列中的位置出现。
如何设置非唯一索引以保持插入顺序?我试着用ordered_non_unique和sequenced制作一个composite_key,但由于sequenced不是一个键索引,它不会编译。
这里有一个最小的例子(实时版本在这里):
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <iostream>
#include <vector>
using namespace boost::multi_index;
using namespace std;
struct Entry {
int nonUniqueInt;
string somethingExtra;
};
using Container_t = multi_index_container<Entry, indexed_by<
sequenced<>,
ordered_non_unique<
// ***** What can I put here? *****
member<Entry, int, &Entry::nonUniqueInt>
>
>>;
std::vector<Entry> const sampleData{
{1, "first"}, {2, "second"}, {3, "third"}, {3, "fourth"}, {2, "fifth"}, {1, "sixth"}
};
// fillFront should make the sequence LIFO
template <typename T>
void fillFront(T & container) {
for (auto & item : sampleData) {
container.push_front(item);
}
}
// fillBack should make the sequence FIFO
template <typename T>
void fillBack(T & container) {
for (auto & item : sampleData) {
container.push_back(item);
}
}
int main() {
Container_t container;
auto & sequenced = container.get<0>();
auto & ordered = container.get<1>();
fillFront(sequenced);
for(auto & entry : ordered) {
cout << entry.nonUniqueInt << ": " << entry.somethingExtra << endl;
}
cout << endl;
container.clear();
fillBack(sequenced);
for(auto & entry : ordered) {
cout << entry.nonUniqueInt << ": " << entry.somethingExtra << endl;
}
}
// Expected/desired output: Actual output:
// 1: sixth 1: first
// 1: first 1: sixth
// 2: fifth 2: second
// 2: second 2: fifth
// 3: fourth 3: third
// 3: third 3: forth
//
// 1: first 1: first
// 1: sixth 1: sixth
// 2: second 2: second
// 2: fifth 2: fifth
// 3: third 3: third
// 3: forth 3: forth
您希望在有序索引中,对于相等的键,项"保持稳定"。
Boost Multi Index不支持。你所能做的"最好"就是按照迭代器的外观在插入顺序索引中排序。
使用random_access索引。
using Container_t = multi_index_container<Entry, indexed_by<
random_access<>,
ordered_non_unique< member<Entry, int, &Entry::nonUniqueInt> >
>>;
下面是一个示例:
int main() {
Container_t container;
auto & sequenced = container.get<0>();
fillFront(sequenced);
stabled_ordered(container, [](Entry const& entry) {
cout << entry.nonUniqueInt << ": " << entry.somethingExtra << endl;
});
cout << endl;
container.clear();
fillBack(sequenced);
stabled_ordered(container, [](Entry const& entry) {
cout << entry.nonUniqueInt << ": " << entry.somethingExtra << endl;
});
}
查看Live On Coliru
神奇的当然是stabled_ordered
,它是std::for_each
的修改版本,接受一个容器和一个函子:
template <typename Container, typename F, int RA = 0, int ONU = 1>
F stabled_ordered(Container const& container, F&& f);
实现迭代order - nonunique索引(由ONU
模板参数表示)并调用函子,但在具有等效键的范围内以插入顺序(由RA
(random_access
)表示)调用:
template <typename Container, typename F, int RA = 0, int ONU = 1>
F stabled_ordered(Container const& container, F&& f)
{
using RAIt = typename Container::template nth_index<RA> ::type::const_iterator;
using ONUIt = typename Container::template nth_index<ONU>::type::const_iterator;
auto& ordered = container.template get<ONU>();
for(ONUIt cursor = ordered.begin(); cursor != ordered.end(); )
{
// get range with equiv. keys
auto key_range = ordered.equal_range(ordered.key_extractor()(*cursor));
cursor = key_range.second;
// project into first index
std::vector<RAIt> v;
for(auto it = key_range.first; it != key_range.second; ++it)
v.push_back(boost::multi_index::project<RA>(container, it));
// put into original order
std::sort(v.begin(), v.end());
for_each(v.begin(), v.end(), [&f](RAIt const& it) { f(*it); });
}
return std::forward<F>(f);
}
不要被typename .... ::template
咒语吓倒:这些只是因为我想让算法实现比你可能需要的更通用:)
相关文章:
- 数组索引的值没有增加
- 芬威克树(BIT).找到具有给定累积频率的最小索引,单位为 O(logN)
- 为什么 std::unique 不调用 std::sort?
- 查找最接近的大于当前数字的数字的索引
- 在C++中调整向量中的索引
- 重载元组索引运算符-C++
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 为std::string的某个索引赋值
- 并行用于C++17中数组索引范围内的循环
- 跟随整数索引列表的自定义类迭代器
- 如何在for循环中包含两个索引值的测试条件
- D3D11-将混合权重和索引传递到顶点着色器
- 将转换字符键入 int 以用作向量C++的索引
- 在 C++ 中访问数组负索引处的内存不会返回垃圾
- 如何为圆环创建索引
- 在子集化后将包含索引号的列表列表映射到标准索引序列
- 查找字符在两个索引之间出现的次数
- Azure Kinect 使用正文索引映射裁剪正文
- 如何查找哪个类对象位于数组的特定索引上(多态性)
- 数组索引重载错误