C++ 具有或搜索功能的多密钥容器
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入一个保留值(如0),它将被视为“或”搜索 我正在处理各种数据,这些数据与多种算法相互关联。然而,每个算法拥有的信息不足以完全正确地定义所有密钥来收集每个单独的信息包。在稍后的阶段,所有信息都将被传递到一个更为中心的数据库(可能使用SQLite或其他什么,在这个阶段不知道) 我对C++的大部分内容还是比较新的,目前对数据库一无所知。另一方面,我确实有时间学习东西。对不起,如果这是一个模糊的问题,但由于可能必须学习卡上至少一种新的语言,我想我可以问一些方向!提前感谢您的帮助C++ 具有或搜索功能的多密钥容器,c++,qt,containers,C++,Qt,Containers,我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入一个保留值(如0),它将被视为“或”搜索 我正在处理各种数据,这些数据与多种算法相互关联。然而,每个算法拥有的信息不足以完全正确地定义所有密钥来收集每个单独的信息包。在稍后的阶段,所有信息都将被传递到一个更为中心的数据库(可能使用SQLite或其他什么,在这个阶段不知道) 我对C++的大部分内容还是比较新的,目前对数据库一无所知。另一方面,我确实有时间学习东西。对不起,如果这是一个模糊的问题,但由于可能必须学习卡上至少一种新的语言,我想
当前使用:Qt与C++在Windows 7或Ubuntu 12.04
< P>这里有一个版本(它……覆盖你的输入),使用Booo::多索引:#include <set>
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
using namespace boost::multi_index;
template <typename T, typename KeyElementType = int>
class or_container
{
typedef KeyElementType key_element_type;
struct default_index{};
struct keyx_index{};
struct keyy_index{};
struct datum
{
datum(const std::pair<key_element_type, key_element_type>& key, T value)
: key_x(key.first)
, key_y(key.second)
, value(value)
{
assert(0 != key_x);
assert(0 != key_y);
}
datum(key_element_type key_x, key_element_type key_y, T value)
: key_x(key_x)
, key_y(key_y)
, value(value)
{
assert(0 != key_x);
assert(0 != key_y);
}
std::pair<key_element_type, key_element_type> get_key() const
{
return std::make_pair(key_x, key_y);
}
operator const T& () const
{
return value;
}
operator T& ()
{
return value;
}
key_element_type key_x;
key_element_type key_y;
T value;
};
typedef multi_index_container
<
datum
, indexed_by
<
ordered_non_unique<tag<default_index>, const_mem_fun<datum, std::pair<key_element_type, key_element_type>, &datum::get_key> >
, ordered_non_unique<tag<keyx_index>, member<datum, key_element_type, &datum::key_x> >
, ordered_non_unique<tag<keyy_index>, member<datum, key_element_type, &datum::key_y> >
>
> container;
container m_cont;
public:
typedef std::pair<key_element_type, key_element_type> key_type;
or_container()
{}
//! precondition: key indices do not contain 0 values.
//! @return whether the value was inserted for the specified key.
bool insert(key_type key, const T& value)
{
assert(key.first != 0 && key.second != 0);
if (!key.first || !key.second)
return false;
return m_cont.insert(datum(key, value)).second;
}
std::size_t size() const { return m_cont.size(); }
std::set< std::reference_wrapper<const T> > find(key_type key) const
{
std::set< std::reference_wrapper<const T> > values;
if (key.first != 0 && key.second != 0)
{
const auto& index = m_cont.get<default_index>();
std::transform(index.lower_bound(key), index.upper_bound(key), std::inserter(values, values.end()), [](const datum& d){ return std::reference_wrapper<const T>(d); });
}
else if (key.first == 0 && key.second == 0)
{
std::transform(m_cont.begin(), m_cont.end(), std::inserter(values, values.end()), [](const datum& d){ return std::reference_wrapper<const T>(d); });
}
else
{
if (key.first == 0)
{
const auto& index = m_cont.get<keyy_index>();
std::transform(index.lower_bound(key.second), index.upper_bound(key.second), std::inserter(values, values.end()), [](const datum& d){ return std::reference_wrapper<const T>(d); });
}
if (key.second == 0)
{
const auto& index = m_cont.get<keyx_index>();
std::transform(index.lower_bound(key.first), index.upper_bound(key.first), std::inserter(values, values.end()), [](const datum& d){ return std::reference_wrapper<const T>(d); });
}
}
return values;
}
};
template <typename T, typename Cmp, typename Alloc>
std::ostream& operator << (std::ostream& os, const std::set<T, Cmp, Alloc>& s)
{
os << "{ ";
int i = 0;
for (T value : s)
{
if (i++)
os << ", ";
os << value;
};
os << " }";
return os;
}
int main()
{
using namespace std;
or_container<int> myContainer;
myContainer.insert(make_pair(1, 1), 650);
myContainer.insert(make_pair(2, 4), 827);
myContainer.insert(make_pair(3, 1), 5);
myContainer.insert(make_pair(3, 2), 943254);
pair<int, int> key1 = make_pair(1, 1);
pair<int, int> key2 = make_pair(3, 0);
pair<int, int> key3 = make_pair(0, 1);
pair<int, int> key4 = make_pair(0, 0);
auto s = myContainer.find(key1);
cout << s << endl; // it->second is an array or vector or values
s = myContainer.find(key2);
cout << s << endl; // I know this isn't how to output all values in a vector
s = myContainer.find(key3);
cout << s << endl; // But this demonstrates the sort of thing I'm after
s = myContainer.find(key4);
cout << s << endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间boost::multi_索引;
模板
类或类容器
{
类型定义键元素类型键元素类型;
结构默认_索引{};
结构keyx_索引{};
结构keyy_索引{};
结构基准
{
基准(常数标准::配对和键,T值)
:key_x(key.first)
,key_y(key.second)
,value(value)
{
断言(0!=键x);
断言(0!=key_y);
}
基准(键元素键类型键x、键元素键类型键y、T值)
:键x(键x)
,key_y(key_y)
,value(value)
{
断言(0!=键x);
断言(0!=key_y);
}
std::pair get_key()常量
{
返回std::make_pair(key_x,key_y);
}
运算符常量T&()常量
{
返回值;
}
算子T&()
{
返回值;
}
键\元素\类型键\ x;
键\元素\类型键\ y;
T值;
};
typedef多索引容器
<
资料
,由
<
有序非唯一
,有序\u非唯一
,有序\u非唯一
>
>容器;
集装箱运输;
公众:
typedef std::对密钥类型;
或_容器()
{}
//!前提条件:键索引不包含0个值。
//!@返回是否为指定的键插入了值。
布尔插入(键类型键、常数和值)
{
断言(key.first!=0&&key.second!=0);
如果(!key.first | |!key.second)
返回false;
返回m_cont.insert(基准(键、值))。秒;
}
std::size_t size()常量{返回m_cont.size();}
std::setfind(键类型键)常量
{
std::set值;
如果(key.first!=0&&key.second!=0)
{
const auto&index=m_cont.get();
std::transform(index.lower_-bound(key)、index.upper_-bound(key)、std::inserter(values、values.end())、[](const-datum&d){return std::reference_-wrapper(d);});
}
else if(key.first==0&&key.second==0)
{
std::transform(m_cont.begin()、m_cont.end()、std::inserter(values、values.end())、[](常量数据和d){return std::reference_wrapper(d);});
}
其他的
{
如果(key.first==0)
{
const auto&index=m_cont.get();
std::transform(index.lower_-bound(key.second)、index.upper_-bound(key.second)、std::inserter(values、values.end())、[](const-datum&d){return std::reference_-wrapper(d);});
}
如果(key.second==0)
{
const auto&index=m_cont.get();
std::transform(index.lower_-bound(key.first)、index.upper_-bound(key.first)、std::inserter(values、values.end())、[](const-datum&d){return std::reference_-wrapper(d);});
}
}
返回值;
}
};
模板
std::ostream&operatorBrandon答案的变体:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/range/any_range.hpp>
#include <iostream>
using namespace boost::multi_index;
struct element{int k1,k2,data;};
typedef multi_index_container<
element,
indexed_by<
ordered_unique<
composite_key<
element,
member<element,int,&element::k1>,
member<element,int,&element::k2>
>
>,
ordered_non_unique<member<element,int,&element::k2>>
>
> multi_t;
typedef boost::any_range<
element,
boost::bidirectional_traversal_tag,
const element&,
std::ptrdiff_t
> range_t;
inline range_t range(const multi_t& m,const std::pair<int,int>& k)
{
if(k.second==0){
if(k.first==0){
return range_t(m.begin(),m.end());
}
else{
auto p=m.equal_range(k.first);
return range_t(p.first,p.second);
}
}
else if(k.first==0){
auto p=m.get<1>().equal_range(k.second);
return range_t(p.first,p.second);
}
else{
auto p=m.equal_range(boost::make_tuple(k.first,k.second));
return range_t(p.first,p.second);
}
}
inline std::ostream& operator<<(std::ostream& os,const range_t& r)
{
for(const auto& e:r){
os<<e.data<<",";
}
return os;
}
int main()
{
multi_t m={{1,1,650},{2,4,827},{3,1,5},{3,2,943254}};
std::cout<<range(m,{1,1})<<"\n";
std::cout<<range(m,{3,0})<<"\n";
std::cout<<range(m,{0,1})<<"\n";
std::cout<<range(m,{0,0})<<"\n";
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间boost::multi_索引;
结构元素{intk1,k2,data;};
typedef多索引容器<
元素,
索引<
有序_唯一<
复合键<
元素,
委员:,
成员
>
>,
有序非唯一
>
>多元文化;
typedef boost::任意_范围<
元素,
boost::双向遍历标记,
常量元素&,
标准:ptrdiff\t
>射程;
内联范围\u t范围(常数多\u t&m,常数标准::配对和k)
{
如果(k.second==0){
如果(k.first==0){
返回范围(m.begin(),m.end());
}
否则{
自动p=m.等_范围(k.优先);
返回范围(p.first,p.second);
}
}
else如果(k.first==0){
自动p=m.get().相等范围(k秒);
返回范围(p.first,p.second);
}
否则{
自动p=m.equal_范围(boost::make_tuple(k.first,k.second));
返回范围(p.first,p.second);
}
}
inline std::ostream&operator这里有一个版本,它只使用stl(我认为是C++03)和Joaqín提出的一些优化:
#include <map>
#include <set>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <iostream>
template <typename T, typename KeyElementType = int>
class or_container
{
typedef KeyElementType key_element_type;
struct datum
{
datum(const std::pair<key_element_type, key_element_type>& key, T value)
: key(key)
, value(value)
{
assert(0 != key.first);
assert(0 != key.second);
}
operator const T& () const
{
return value;
}
bool operator <(const datum& rhs) const
{
return key < rhs.key;
}
bool operator <(const key_element_type& rhs) const
{
return key.first < rhs;
}
friend bool operator <(const key_element_type& lhs, const datum& rhs)
{
return lhs < rhs.key.first;
}
bool operator <(const std::pair<key_element_type, key_element_type>& rhs) const
{
return key < rhs;
}
friend bool operator <(const std::pair<key_element_type, key_element_type>& lhs, const datum& rhs)
{
return lhs < rhs.key;
}
std::pair<key_element_type, key_element_type> key;
T value;
};
typedef std::multiset<datum> data_set;
typedef typename data_set::iterator datum_iterator;
data_set m_cont;
typedef std::multimap<key_element_type, datum_iterator> y_index;
y_index m_yindex;
public:
typedef std::pair<key_element_type, key_element_type> key_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
or_container()
{}
//! precondition: key indices do not contain 0 values.
//! @return whether the value was inserted for the specified key.
bool insert(key_type key, const T& value)
{
assert(key.first != 0 && key.second != 0);
if (!key.first || !key.second)
return false;
datum_iterator it = m_cont.insert(datum(key, value));
m_yindex.insert(std::make_pair(key.second, it));
return true;
}
std::size_t size() const { return m_cont.size(); }
std::multiset<T> find(const key_type& key) const
{
struct deref_map_iter_value
{
const_reference operator()(const typename y_index::value_type& item) { return *item.second; }
};
std::multiset<T> values;
if (key.second == 0)
if (key.first == 0)
std::copy(m_cont.begin(), m_cont.end(), std::inserter(values, values.end()));
else
std::copy(std::lower_bound(m_cont.begin(), m_cont.end(), key.first), std::upper_bound(m_cont.begin(), m_cont.end(), key.first), std::inserter(values, values.end()));
else if (key.first == 0)
std::transform(m_yindex.lower_bound(key.second), m_yindex.upper_bound(key.second), std::inserter(values, values.end()), deref_map_iter_value());
else
std::copy(std::lower_bound(m_cont.begin(), m_cont.end(), key), std::upper_bound(m_cont.begin(), m_cont.end(), key), std::inserter(values, values.end()));
return values;
}
};
template <typename T, typename Cmp, typename Alloc>
std::ostream& operator << (std::ostream& os, const std::multiset<T, Cmp, Alloc>& s)
{
os << "{ ";
int i = 0;
for (T value : s)
{
if (i++)
os << ", ";
os << value;
};
os << " }";
return os;
}
int main()
{
using namespace std;
or_container<int> myContainer;
myContainer.insert(make_pair(1, 1), 650);
myContainer.insert(make_pair(2, 4), 827);
myContainer.insert(make_pair(3, 1), 5);
myContainer.insert(make_pair(3, 2), 943254);
pair<int, int> key1 = make_pair(1, 1);
pair<int, int> key2 = make_pair(3, 0);
pair<int, int> key3 = make_pair(0, 1);
pair<int, int> key4 = make_pair(0, 0);
std::multiset<int> s = myContainer.find(key1);
cout << s << endl; // it->second is an array or vector or values
s = myContainer.find(key2);
cout << s << endl; // I know this isn't how to output all values in a vector
s = myContainer.find(key3);
cout << s << endl; // But this demonstrates the sort of thing I'm after
s = myContainer.find(key4);
cout << s << endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
模板
类或类容器
{
类型定义键元素类型键元素类型;
结构基准
{
基准(常数标准::配对和键,T值)
:键(key)
,value(value)
{
断言(0!=key.first);
断言(0!=key.second);
}
运算符常量T&()常量
{
返回值;
}
bool操作符我觉得你需要实现你自己的类。我不认为STL有什么现成的东西可以满足你的需要。我已经创建了几个类
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/range/any_range.hpp>
#include <iostream>
using namespace boost::multi_index;
struct element{int k1,k2,data;};
typedef multi_index_container<
element,
indexed_by<
ordered_unique<
composite_key<
element,
member<element,int,&element::k1>,
member<element,int,&element::k2>
>
>,
ordered_non_unique<member<element,int,&element::k2>>
>
> multi_t;
typedef boost::any_range<
element,
boost::bidirectional_traversal_tag,
const element&,
std::ptrdiff_t
> range_t;
inline range_t range(const multi_t& m,const std::pair<int,int>& k)
{
if(k.second==0){
if(k.first==0){
return range_t(m.begin(),m.end());
}
else{
auto p=m.equal_range(k.first);
return range_t(p.first,p.second);
}
}
else if(k.first==0){
auto p=m.get<1>().equal_range(k.second);
return range_t(p.first,p.second);
}
else{
auto p=m.equal_range(boost::make_tuple(k.first,k.second));
return range_t(p.first,p.second);
}
}
inline std::ostream& operator<<(std::ostream& os,const range_t& r)
{
for(const auto& e:r){
os<<e.data<<",";
}
return os;
}
int main()
{
multi_t m={{1,1,650},{2,4,827},{3,1,5},{3,2,943254}};
std::cout<<range(m,{1,1})<<"\n";
std::cout<<range(m,{3,0})<<"\n";
std::cout<<range(m,{0,1})<<"\n";
std::cout<<range(m,{0,0})<<"\n";
}
#include <map>
#include <set>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <iostream>
template <typename T, typename KeyElementType = int>
class or_container
{
typedef KeyElementType key_element_type;
struct datum
{
datum(const std::pair<key_element_type, key_element_type>& key, T value)
: key(key)
, value(value)
{
assert(0 != key.first);
assert(0 != key.second);
}
operator const T& () const
{
return value;
}
bool operator <(const datum& rhs) const
{
return key < rhs.key;
}
bool operator <(const key_element_type& rhs) const
{
return key.first < rhs;
}
friend bool operator <(const key_element_type& lhs, const datum& rhs)
{
return lhs < rhs.key.first;
}
bool operator <(const std::pair<key_element_type, key_element_type>& rhs) const
{
return key < rhs;
}
friend bool operator <(const std::pair<key_element_type, key_element_type>& lhs, const datum& rhs)
{
return lhs < rhs.key;
}
std::pair<key_element_type, key_element_type> key;
T value;
};
typedef std::multiset<datum> data_set;
typedef typename data_set::iterator datum_iterator;
data_set m_cont;
typedef std::multimap<key_element_type, datum_iterator> y_index;
y_index m_yindex;
public:
typedef std::pair<key_element_type, key_element_type> key_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
or_container()
{}
//! precondition: key indices do not contain 0 values.
//! @return whether the value was inserted for the specified key.
bool insert(key_type key, const T& value)
{
assert(key.first != 0 && key.second != 0);
if (!key.first || !key.second)
return false;
datum_iterator it = m_cont.insert(datum(key, value));
m_yindex.insert(std::make_pair(key.second, it));
return true;
}
std::size_t size() const { return m_cont.size(); }
std::multiset<T> find(const key_type& key) const
{
struct deref_map_iter_value
{
const_reference operator()(const typename y_index::value_type& item) { return *item.second; }
};
std::multiset<T> values;
if (key.second == 0)
if (key.first == 0)
std::copy(m_cont.begin(), m_cont.end(), std::inserter(values, values.end()));
else
std::copy(std::lower_bound(m_cont.begin(), m_cont.end(), key.first), std::upper_bound(m_cont.begin(), m_cont.end(), key.first), std::inserter(values, values.end()));
else if (key.first == 0)
std::transform(m_yindex.lower_bound(key.second), m_yindex.upper_bound(key.second), std::inserter(values, values.end()), deref_map_iter_value());
else
std::copy(std::lower_bound(m_cont.begin(), m_cont.end(), key), std::upper_bound(m_cont.begin(), m_cont.end(), key), std::inserter(values, values.end()));
return values;
}
};
template <typename T, typename Cmp, typename Alloc>
std::ostream& operator << (std::ostream& os, const std::multiset<T, Cmp, Alloc>& s)
{
os << "{ ";
int i = 0;
for (T value : s)
{
if (i++)
os << ", ";
os << value;
};
os << " }";
return os;
}
int main()
{
using namespace std;
or_container<int> myContainer;
myContainer.insert(make_pair(1, 1), 650);
myContainer.insert(make_pair(2, 4), 827);
myContainer.insert(make_pair(3, 1), 5);
myContainer.insert(make_pair(3, 2), 943254);
pair<int, int> key1 = make_pair(1, 1);
pair<int, int> key2 = make_pair(3, 0);
pair<int, int> key3 = make_pair(0, 1);
pair<int, int> key4 = make_pair(0, 0);
std::multiset<int> s = myContainer.find(key1);
cout << s << endl; // it->second is an array or vector or values
s = myContainer.find(key2);
cout << s << endl; // I know this isn't how to output all values in a vector
s = myContainer.find(key3);
cout << s << endl; // But this demonstrates the sort of thing I'm after
s = myContainer.find(key4);
cout << s << endl;
return 0;
}