使用STL对两个元素进行排序

Sorting just two elements using STL

我经常有两个变量 foo1foo2,它们是数字类型。它们代表某物的界限

用户为他们提供价值,但就像一个顽固的音乐家,不一定是正确的顺序!

所以我的代码中充斥着像

这样的代码
if (foo2 < foo1){
    std::swap(foo2, foo1);
}

当然,这是一种惯用排序,其中两个元素在内存中不一定连续。这让我想知道:是否有用于此的 STL 单行代码?

不,但是当您注意到您将相同的代码写了两次时,是时候为它编写一个函数了:

template<typename T, typename P = std::less<T>>
void swap_if(T& a, T& b, P p = P()) {
    if (p(a, b)) {
        using std::swap;
        swap(a, b);
    }
}

如果您要比较的值的数据类型尚未在 C++ 中。您需要重载比较运算符。

例如,如果你想比较 foo1 和 foo2

template <class T>
class Foo { 
  private: 
    int value;     // value 

  public: 
    int GetValue() const {
        return value;
    }
}; 

bool operator<(const Foo& lhs, const Foo& rhs) {
    return (lhs.GetValue() < rhs.GetValue());
}

如果您的值是某种类型的 int 或 double。然后就可以使用std::list<>::sort成员函数了。

例如:

std::list<int> integer_list;
int_list.push_back(1);
int_list.push_back(8);
int_list.push_back(9);
int_list.push_back(7);
int_list.sort();

for(std::list<int>::iterator list_iter = int_list.begin(); list_iter != int_list.end(); list_iter++)
{
    std::cout<<*list_iter<<endl;
}

我建议退后一步,让类型系统为您完成工作:引入像 Bounds(或 Interval)这样的类型来解决这个问题。像

template <typename T>
class Interval {
public:
  Interval( T start, T end ) : m_start( start ), m_end( end ) {
    if ( m_start > m_end ) {
      std::swap( m_start, m_end );
    }
  }

  const T &start() const { return m_start; }
  const T &end() const { return m_end; }

private:
  T m_start, m_end;
};

这不仅集中了交换排序代码,还有助于尽早确定正确的顺序,这样您就不会一直传递两个元素,这意味着您甚至不需要一开始经常检查订单。

另一种避免该问题的方法是将边界表示为一对 'start value' 和 'length',其中 'length' 是无符号值。

std::minmax returns 一对最小和最大的元素。您可以将其与 std::tie.

一起使用
#include <algorithm>
#include <tuple>
#include <iostream>

int main()
{
    int a = 7;
    int b = 5;
    std::tie(a, b) = std::minmax({a,b});
    std::cout << a << " " << b; // output: 5 7
}

请注意,这与 if(a < b) std::swap(a,b); 版本不同。例如,这不适用于仅移动元素。