【问题标题】:Does STL or BOOST provide any clean way to get the sort order without reordering original sequence?STL 或 BOOST 是否提供任何干净的方法来获得排序顺序而无需重新排序原始序列?
【发布时间】:2011-06-27 21:57:26
【问题描述】:

我想查找向量的排序顺序,例如,不重新排序向量。

我可以想到几种方法来做到这一点,我想知道我是否缺少一些内置的 STL 或 BOOST 方法来做到这一点。

我想如果功能可用,代码最终会看起来像这样:

std::vector<float> unsortedSeq;
unsortedSeq.push_back( 1.1 );
unsortedSeq.push_back( 1.0 );
unsortedSeq.push_back( 0.5 );
unsortedSeq.push_back( 1.2 );
unsortedSeq.push_back( 1.15 );

std::list<std::size_t> sortOrder;

std::sort_indices( unsortedSeq.begin(), unsortedSeq.end(), sortOrder.begin() );

BOOST_FOREACH( std::size_t index, sortOrder )
{
    std::cout << index << "\n"
}



2
1
0
4
3

任何人都知道任何 STL 或 BOOST-sims 可以做到我所要求的,如图所示?

【问题讨论】:

    标签: c++ sorting boost stl


    【解决方案1】:
    std::vector<float> v;
    // filled somewhere else
    
    std::vector<std::size_t> indices(v.size());
    // iota is from <numeric>, C++0x
    std::iota(indices.begin(), indices.end(), 0);
    
    std::sort(indices.begin(), indices.end(), [&v](std::size_t left, std::size_t right)
    {
        return v[left] < v[right];
    });
    

    【讨论】:

      【解决方案2】:

      你会这样做:

      template<typename T>
      class SortOrder
      {
      public:
          SortOrder(const std::vector<T> *_sortArray) : sortArray(_sortArray) {;}
      
          bool operator()(int lhs, int rhs) const
          {
              return sortArray[lhs] < sortArray[rhs];
          }
      
      private:
          const std::vector<T> *sortArray;
      };
      
      //To do the sorting:
      
      #include <boost/range/counting_range.hpp>
      auto countRange = boost::range::counting_range(0, myListOfStuff.size());
      
      //Build a vector<int> that has one index for every value in your actual vector.
      vector<int> indexList(countRange.begin(), countRange.end());
      
      std::sort(indexList.begin(), indexList.end(), SortOrder(&myListOfStuff));
      

      这会生成一个索引向量,然后根据实际内容的向量对它们进行排序。

      【讨论】:

      • 这很优雅。我喜欢它。
      • 希望比较器获取并存储ref-to-const,但我可能只是很挑剔:)
      • @Tomalak:我没有使用引用的原因是std::sort 可能会调用SortOrder 的复制赋值运算符。我认为规范允许这样做,但我不确定,并且没有拥有规范的副本,我决定谨慎行事。但我会将其更改为 const 指针,因为我们根本不应该更改内容。
      【解决方案3】:

      没有;你必须自己做。

      幸运的是,这很容易! (这可能是没有提供的原因)

      • 考虑输入向量v
      • 创建一个索引为 0..n 的向量,其中 n 是您的输入 v 的大小
      • std::sort 索引向量,提供对输入 v 的引用,以及返回 v[left] &lt; v[right] 的自定义比较器。

      【讨论】:

        【解决方案4】:

        另一个例子,使用boost::ref...

        #include <algorithm>
        #include <iostream>
        #include <vector>
        #include <iterator>
        
        #include <boost/ref.hpp>
        
        int main()
        {
            int n[] = { 3, 4, 1, 7, 10 };
            std::vector<int> v(n, n + 5);
        
            // print the original sequence
            std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
            std::cout << std::endl;
        
            // fill another vector with references to the data in the original
            std::vector<boost::reference_wrapper<int> > vp;
            std::transform(v.begin(), v.end(), std::back_inserter(vp), &boost::ref<int>);
        
            // sort the references
            std::sort(vp.begin(), vp.end());
        
            // print the filtered version.
            std::copy(vp.begin(), vp.end(), std::ostream_iterator<int>(std::cout, " "));
            std::cout << std::endl;
        
            // print the original sequence again to show it hasnt changed
            std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
            std::cout << std::endl;
        }
        

        【讨论】:

          【解决方案5】:

          只需对Nicol Bolas' answer 进行一些修改,就可以将任何随机访问迭代器用作输入(只要它是随机迭代器并且具有reference 类型成员)。 还可以提供比较函数(就像在std::sort 中一样,默认为std::less)。

          template<typename const_iterator>
          class SortOrder
          {
          public:
              using Compare = std::function<bool(typename const_iterator::reference, typename const_iterator::reference)>;
              SortOrder(const_iterator to_sort, Compare comp = std::less<typename const_iterator::reference>()) :
                  to_sort_(to_sort),
                  comp_(comp)
              {}
          
              bool operator()(int lhs, int rhs) const
              {
                  return comp_(*(to_sort_ + lhs), *(to_sort_ + rhs));
              }
          
          private:
              const_iterator to_sort_;
              Compare comp_;
          };
          
          vector<double> to_sort{1, 5, 9, 2, 6, 17, 2, 8.5};
          
          // Create integers, one value for each to_sort element
          auto count_range = boost::counting_range(size_t(0), to_sort.size());
          vector<int> indices(count_range.begin(), count_range.end());
          // indices = 0 1 2 3 4 5 6 7
          
          auto it = to_sort.begin();
          sort(indices.begin(), indices.end(), SortOrder<decltype(it)>(it));
          // indices = 0 3 6 1 4 7 2 5
          

          可以找到一个工作示例here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-02-22
            • 1970-01-01
            • 1970-01-01
            • 2020-02-04
            • 1970-01-01
            • 2011-10-03
            • 2021-04-23
            • 2021-01-02
            相关资源
            最近更新 更多