考虑std::map<K,V>
。我希望通过适当的容器std::C<V*>
或std::C<V&>
获取值来重新排序地图,其方式是不执行任何值的副本以将元素存储在C中。此外,C中的元素必须根据应用于每个元素的int f(V&)
的结果进行排序。尽管我努力,但我找不到合适的C和足够有效的方法来构建它。你有什么解决方案吗?一个小例子将非常感激。
答案 0 :(得分:2)
看起来很简单。
std::map<K,V> src;
int f(V&) {return 0;}
V* get_second(std::pair<const K,V> &r) {return &(r.second);} //transformation
bool pred(V* l, V* r) { return f(*l)<f(*r); } //sorting predicate
std::vector<V*> dest(src.size()); //make destination big enough
std::transform(src.begin(), src.end(), dest.begin(), get_second); //transformcopy
std::sort(dest.begin(), dest.end(), pred); //sort
除非你的意思是C应该是另一张地图:
std::pair<K,V*> shallow_pair(std::pair<const K,V> &r)
{return std::pair<K,V*>(r.first, &(r.second));}
std::map<K, V*> dest2;
std::transform(src.begin(), src.end(),
std::inserter(dest2,dest2.end()), shallow_pair);
这要求之前的地图保留在范围更长而不是dest
,并且在dest
被销毁之前不会移除任何对。否则src
将需要持有某种智能指针。
答案 1 :(得分:2)
您可以使用std::reference_wrapper
,如下所示:
#include <map>
#include <string>
#include <algorithm>
#include <functional>
#include <prettyprint.hpp>
#include <iostream>
template <typename T>
std::ostream & operator<<(std::ostream & o, std::reference_wrapper<T> const & rw)
{
return o << rw.get();
}
int main()
{
std::map<int, std::string> m { { 1, "hello"}, { 2, "aardvark" } };
std::cout << m << std::endl;
std::vector<std::reference_wrapper<std::string>> v;
for (auto & p : m) v.emplace_back(p.second);
std::cout << v << std::endl;
std::sort(v.begin(), v.end(), std::less<std::string>); // or your own predicate
std::cout << v << std::endl;
v.front().get() = "world";
std::cout << m << std::endl;
}
打印:
[(1, hello), (2, aardvark)]
[hello, aardvark]
[aardvark, hello]
[(1, hello), (2, world)]
答案 2 :(得分:1)
听起来您正在使用多个容器将多个视图表示到同一数据集中。这种方法的问题在于保持容器同步并避免悬挂指针问题。 Boost.MultiIndex就是出于这个目的。 boost::multi_index
容器只存储每个元素的一个副本,但允许您通过多个索引访问元素。
示例:
#include <iterator>
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/member.hpp>
typedef std::string Key;
typedef int Value;
struct Record
{
Record(const Key& key, Value value) : key(key), value(value) {}
Key key;
Value value;
};
inline std::ostream& operator<<(std::ostream& os, const Record& rec)
{
os << rec.key << " " << rec.value << "\n";
return os;
}
inline int sortFunc(const Record& rec) {return -rec.value;}
struct ByNumber{}; // tag
namespace bmi = boost::multi_index;
typedef bmi::multi_index_container<
Record,
bmi::indexed_by<
// sort by key like a std::map
bmi::ordered_unique< bmi::member<Record, Key, &Record::key> >,
// sort by less<int> on free function sortFunc(const Record&)
bmi::ordered_non_unique<bmi::tag<ByNumber>,
bmi::global_fun<const Record&, int, &sortFunc> >
>
> RecordSet;
typedef RecordSet::index<ByNumber>::type RecordsByNumber;
int main()
{
RecordSet rs;
rs.insert(Record("alpha", -1));
rs.insert(Record("charlie", -2));
rs.insert(Record("bravo", -3));
RecordsByNumber& byNum = rs.get<ByNumber>();
std::ostream_iterator<Record> osit(std::cout);
std::cout << "Records sorted by key:\n";
std::copy(rs.begin(), rs.end(), osit);
std::cout << "\nRecords sorted by sortFunc(const Record&):\n";
std::copy(byNum.begin(), byNum.end(), osit);
}
结果:
Records sorted by key: alpha -1 bravo -3 charlie -2 Records sorted by sortFunc(const Record&): alpha -1 charlie -2 bravo -3
答案 3 :(得分:0)
我开始的地方是:
std::map<K,V,C>
中,其中C是比较器类)答案 4 :(得分:0)
怎么样,
std::set<boost::shared_ptr<V>, compfunc>
其中compfunc是一个函子,它接受两个shared_ptr对象并在你的函数中应用逻辑?
请原谅我的手机格式不好。
答案 5 :(得分:0)
这样的事情(未经测试的伪代码):
V* g(pair<K,V> &v) { return &v.second; }
bool cmp(V* a, V* b) { return f(*a) < f(*b); }
map<K,V> map;
vector<V*> vec;
vec.reserve(map.size());
transform(map.begin(), map.end(), back_inserter(vec), g);
sort(vec.begin(), vec.end(), cmp);