对std :: vector <int>进行排序,但忽略某个数字

时间:2016-04-21 18:36:15

标签: c++ sorting vector

我有一个大小为10的std::vector<int>,每个条目最初为-1。此向量代表我的游戏排行榜(高分),-1表示该条目没有得分。

std::vector<int> myVector;
myVector.resize(10, -1);

当游戏开始时,我想从文件中加载高分。我加载每一行(最多10行),将找到的值转换为int std::stoi,如果数字> 0,我将其替换为当前在向量中的-1在当前位置。

这一切都有效。现在问题是:

由于文件中的值不一定要排序,我想在加载所有条目后对myVector进行排序。我这样做

std::sort(myVector.begin(), myVector.end());

按升序对其进行排序(在我的游戏中得分越低)。

问题在于,由于向量最初用-1填充,并且高分文件中不一定保存10个条目,因此除了玩家的分数之外,向量可能还包含几个-1。

这意味着当使用上面的代码对矢量进行排序时,所有-1将出现在玩家的分数之前。

我的问题是:如何对矢量进行排序(按升序排列),但所有带-1的条目都将放在最后(因为它们不代表真实分数)?

6 个答案:

答案 0 :(得分:9)

结合分区和排序:

std::sort(v.begin(),
          std::partition(v.begin(), v.end(), [](int n){ return n != -1; }));

如果存储从partition返回的迭代器,则您已经完整地描述了非平凡值的范围,因此您不需要在以后查找-1。

答案 1 :(得分:3)

您可以提供lambda作为sort的参数:

std::sort(myVector.begin(), myVector.end(),[]( int i1, int i2 ) {
    if( i1 == -1 ) return false;
    if( i2 == -1 ) return true;
    return i1 < i2; }
);

这里是demo(从Kerrek复制)

但目前尚不清楚你是如何意识到排序后得分在哪里的。

答案 2 :(得分:2)

根据您的描述,分数似乎永远不会消极。在这种情况下,我建议将得分设为vector unsigned int。您可以定义常量

const unsigned int INFINITY = -1;

并最初使用INFINITY加载矢量。 INFINITY是可以存储在32位无符号整数中的最大正整数(也与2的补码中的-1对应)

然后你可以简单地使用

排序
sort(v.begin(),v.end());

所有INFINITY将在排序后结束。

答案 3 :(得分:0)

带有签名std::sort

bool cmp(const T& a, const T& b); supports using your own comparison function。所以编写自己的函数类似于:

bool sort_negatives(const int& a, const int& b)
{
    if (a == -1) {
        return false;
    }
    if (b == -1) {
        return true;
    }
    return a < b;
}

然后像sort一样致电std::sort(myVector.begin(), myVector.end(), sort_negatives);

编辑:修正了斯拉瓦的逻辑礼貌。如果您使用的是支持C ++ 11的编译器,请使用lambda或分区答案,但这应该适用于C ++ 11之前的编译器。

答案 4 :(得分:0)

对于以下内容,我假设-1值都放在向量的末尾。如果不是,请使用KerrekSB的方法,或者确保不跳过向量中没有有效分数的索引(通过使用额外的索引/迭代器来写入向量)。

std::sort使用一对迭代器。只需提供包含非-1值的子范围。从文件中读取后,您已经知道此范围的结束。如果您已经使用迭代器来填充向量,就像在

中一样
auto it = myVector.begin();
while (...) {
    *it = stoi(...);
    ++it;
}

然后只需使用it代替myVector.end()

std::sort(myVector.begin(), it);

否则(即,当使用索引填充向量时,假设i是值的数量),使用

std::sort(myVector.begin(), myVector.begin() + i);

答案 5 :(得分:0)

另一种方法是使用reserve()代替resize()

std::vector<int> myVector;
myVector.reserve(10);

for each line in file:
  int number_in_line = ...;
  myVector.push_back(number_in_line);

std::sort(myVector.begin(), myVector.end());

这样,向量将只有实际存在的数字,没有额外的(虚假的)值(例如-1)。如果向量需要稍后传递给其他模块或函数进行进一步处理,则不需要知道'-1'值的特殊性。