Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何有效地按值排序地图?_C++_Stl_Sorted - Fatal编程技术网

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