C++ 如何有效地按值排序地图?
考虑一个C++ 如何有效地按值排序地图?,c++,stl,sorted,C++,Stl,Sorted,考虑一个std::map。我想通过一个合适的容器std::C或std::C,通过值获利来重新排序映射,这样就不会复制值来存储C中的元素。此外,C中的元素必须根据应用于每个元素的int f(V&)的结果进行排序。尽管我做了很多努力,但还是找不到合适的C语言和足够有效的方法来构建它。你有什么解决办法吗?请举一个小例子。我的出发点是: 看 通过comparator函数对象从V->K创建排序,该函数对象按照您建议的方式计算f(V&)。(例如,C是比较级) 那么 std::set<boost::s
std::map
。我想通过一个合适的容器std::C
或std::C
,通过值获利来重新排序映射,这样就不会复制值来存储C中的元素。此外,C中的元素必须根据应用于每个元素的int f(V&)
的结果进行排序。尽管我做了很多努力,但还是找不到合适的C语言和足够有效的方法来构建它。你有什么解决办法吗?请举一个小例子。我的出发点是:
- 看
- 通过comparator函数对象从V->K创建排序,该函数对象按照您建议的方式计算f(V&)。(例如,C是比较级)
- 那么
std::set<boost::shared_ptr<V>, compfunc>
std::set
其中compfunc是一个接受两个共享\u ptr对象并在函数中应用逻辑的函子
请原谅,我的手机格式不好。似乎很简单
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
std::map src;
int f(V&){return 0;}
V*get_second(std::pair&r){return&(r.second)}//转换
bool pred(V*l,V*r){return f(*l)类似的东西(未测试的伪代码)怎么样:
V*g(pair&V){return&V.second;}
boolcmp(V*a,V*b){返回f(*a)
您可以使用std::reference\u 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;
}
听起来您正在使用多个容器来表示同一数据集中的多个视图。这种方法的问题在于保持容器同步并避免悬空指针问题。正是出于此目的而创建的。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);
}
#包括
#包括
#包括
#包括
#包括
#包括
typedef std::字符串键;
typedef int值;
结构记录
{
记录(常量键和键,值):键(键),值(值){}
钥匙;
价值观;
};
内联std::ostream&operator此问题不清楚。是否希望新容器包含指向映射值的一组指针,并对其进行排序?目标容器是序列容器还是关联容器?(向量vs映射)+1:看起来是正确的。你能用std::transform
和std::back\u inserter
代替显式循环吗?可能吧,但我不觉得它们增加太多。如果标准库已经有了get\u pair\u first
和get\u pair\u second
一元函数,我可能会这样做。拜托,你已经在使用c++11:[](pair&v){return&v.second}
:-)你认为向量和地图之间哪个更快?@Martin:这取决于你用它做什么。使用非标准库?我想这是公平的。我不熟悉refcomp
,这不是定制的吗?@MooingDuck:多亏了另一个问题中的输入,我去掉了那个可怕的东西。一个明确的std::less
是一个很好的解决方法,但他希望它根据int f(V&)的结果排序…
@MooingDuck:哦,好吧,我没看到。是的,那么你无论如何都需要谓词。我只添加一个注释。
#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)]
#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