c++ - std::vector 未按 std::sort 的预期排序

标签 c++ sorting

我想根据实数 vector 对整数 vector 进行排序。 例如。我有一个整数 vector (1,2,3) 和一个相应的实数 vector (0.3,0.2,0.1)。现在我想对整数进行排序,使对应于最小实数的整数排在第一位,对应于第二小实数的整数排在第二位,依此类推,即整数 vector 应该像 (3,2,1) . 代码是:

int main()
{
    const unsigned int M = 5;
    const unsigned int N = 10;
    Eigen::MatrixXd samples = Eigen::MatrixXd::Random(M,N);
    std::vector<unsigned int> indices(N);
    std::iota(indices.begin(),indices.end(),0);
    std::shuffle(indices.begin(),indices.end(),std::default_random_engine(1.0));
    const unsigned int S = 4;
    std::vector<unsigned int> A(indices.begin(),indices.begin()+S);
    std::vector<unsigned int> B(indices.begin()+S,indices.end());

    std::default_random_engine generator;
    std::uniform_int_distribution<unsigned int> distribution(0,N-1);
    const unsigned int index = distribution(generator);

    std::vector<double> distances(A.size());
    for(unsigned int l=0; l<A.size(); ++l)
    {
        distances[l] = (samples.col(index)-samples.col(A[l])).norm();
    } 
    std::sort(A.begin(),A.end(),[&distances](unsigned int i, unsigned int j){return 
    distances[i]<distances[j];});

    distances.resize(B.size());
    for(unsigned int i=0; i<B.size(); ++i)
    {
        distances[i] = (samples.col(index)-samples.col(B[i])).norm();
    }
    std::cout << "distances:" << std::endl;
    for(unsigned int i=0; i<B.size(); ++i)
    {
        std::cout << distances[i] << " ";
    }
    std::cout << std::endl;
    std::cout << "indices before sorting:" << std::endl;
    for(unsigned int i=0; i<B.size(); ++i)
    {
        std::cout << B[i] << " ";
    }
    std::cout << std::endl;
    std::sort(B.begin(),B.end(),[&distances](unsigned int i, unsigned int j){return 
    distances[i]<distances[j];});
    std::cout << "indices after sorting:" << std::endl;
    for(unsigned int i=0; i<B.size(); ++i)
    { 
        std::cout << B[i] << " ";
    } 
    std::cout << std::endl;

    return 0;
}

输出是:

距离:

2.42122 0.940923 1.45279 1.81009 1.96321 1.76887

排序前的索引:

2 5 4 9 8 7

排序后的索引:

7 8 9 2 5 4

为什么输出不是如下所示?

距离:

2.42122 0.940923 1.45279 1.81009 1.96321 1.76887

排序前的索引:

2 5 4 9 8 7

排序后的索引:

5 4 7 9 8 2

最佳答案

您对不同容器的不同索引感到困惑。

根据您的代码,distance[0] 包含“索引”0的距离,但索引B[0]的距离这是索引 2。

尝试将其与您的排序功能一起使用:

auto sort_lambda = [&samples, &index] (unsigned int l, unsigned int r) {
  auto l_value = (samples.col(index)-samples.col(l)).norm();
  auto r_value = (samples.col(index)-samples.col(r)).norm();
  return l_value < r_value;
};

对于具有索引 vector 和值 vector 的一般情况:您可以创建对应关系图,并使用它从某个索引中获取值:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <unordered_map>
#include <vector>

int main()
{
    using vi = std::vector<int>;
    using vf = std::vector<float>;

    vi indices = {2, 4, 8, 1};
    vf values = {1.5, 0.5, 2.5, 4.5};

    std::unordered_map<int, float> correspondences;
    std::transform(begin(indices), end(indices), begin(values),
        std::inserter(correspondences, end(correspondences)),
        [](int i, float v) { return std::make_pair(i, v); });
    std::sort(begin(indices), end(indices),
        [&correspondences](int l, int r) {
            return correspondences.at(l) < correspondences.at(r);
        });
    // Note that now using values is basically impossible because it wasn't sorted as well ... you'd need to sort it now, too!
    std::copy(begin(indices), end(indices), std::ostream_iterator<int>(std::cout, ", "));
}

(ideone link)

如果索引和/或值具有更复杂的类型,那么您可能需要使用 std::reference_wrapper避免在构建 correspondences 时制作拷贝 map 。

当您需要经常这样做时,将值和索引分开可能没有多大意义!


更一般的,允许“待排序” vector 的重复值:

#include <algorithm>
#include <functional>
#include <iterator>
#include <vector>



template<typename A, typename B>
void sort_according_to(std::vector<A> & to_sort, std::vector<B> const & ref)
{
    using pair_t = std::pair<A, std::reference_wrapper<const B>>;
    std::vector<pair_t> work;
    work.reserve(to_sort.size());
    std::transform(
        std::make_move_iterator(begin(to_sort)),
        std::make_move_iterator(end(to_sort)),
        begin(ref),
        std::back_inserter(work),
        [](A&& a, B const & b) {
            return std::make_pair(std::move(a), std::cref(b));
        });
    std::sort(
        begin(work), end(work),
        [](pair_t const & l, pair_t const & r) {
            return l.second.get() < r.second.get();
        });
    std::transform(
        begin(work), end(work),
        begin(to_sort),
        [](pair_t & p) {
            return std::move(p.first);
        });
}



#include <iostream>


int main()
{
    std::vector<int> ints = {1, 1, 2, 2, 3};
    std::vector<float> floats = {0.1, 1.1, 0.2, 2.2, -3.14};

    sort_according_to(ints, floats);

    std::copy(
        begin(ints), end(ints),
        std::ostream_iterator<int>(std::cout, ", "));

}

(用doesn't make copies but moves数据代替)

关于c++ - std::vector 未按 std::sort 的预期排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59503049/

相关文章:

sql - 如何在SQL Server中查找与给定字符串相似的字符串?

algorithm - 证明合并排序输出输入的排列

Mysql在具有数字和字符组合的char数据类型中排序

c++ - 如何让 CListCtrl 保持其滚动条?

c++ - 在 C++ 中重载 new 和 delete

c++ - 为什么在 std::variant 中禁止引用?

java - 根据字符串成员对对象java进行排序

java - 相同的代码为 Java 7 和 8 产生不同的输出

c++ - void abort() 的声明抛出不同的异常

c++ - 如何将 com 实例转换为变体,以在 idispach 调用中传递它