Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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++;,根据另一个向量对一个向量进行排序_C++_Sorting_Vector - Fatal编程技术网

C++ C++;,根据另一个向量对一个向量进行排序

C++ C++;,根据另一个向量对一个向量进行排序,c++,sorting,vector,C++,Sorting,Vector,我得到的最好的例子是,我想根据名字的分数对它们进行排序 vector <string> Names {"Karl", "Martin", "Paul", "Jennie"}; vector <int> Score{45, 5, 14, 24}; 向量名{“卡尔”、“马丁”、“保罗”、“珍妮”}; 向量得分{45,5,14,24}; 因此,如果我将分数排序为{5,14,24,45},那么名称也应该根据它们的分数进行排序。最好的方法是使用一个结构,它将名称与它们的分数相结

我得到的最好的例子是,我想根据名字的分数对它们进行排序

vector <string> Names {"Karl", "Martin", "Paul", "Jennie"};
vector <int> Score{45, 5, 14, 24};
向量名{“卡尔”、“马丁”、“保罗”、“珍妮”};
向量得分{45,5,14,24};

因此,如果我将分数排序为{5,14,24,45},那么名称也应该根据它们的分数进行排序。

最好的方法是使用一个结构,它将名称与它们的分数相结合,并有一个向量

struct Person
{
    std::string Name;
    int Score;
};
然后可以声明向量:

std::vector<Person> people{ { "Karl", 45 }, { "Martin", 5 }, { "Paul", 14 } };
如果要按降序排序,也可以更改lambda:

std::sort(people.begin(), people.end(), 
               [](const auto& i, const auto& j) { return i.Score > j.Score; } );

一种方法是将名称和分数存储在单个数据结构中,如
std::vector
,然后按如下方式进行排序:

#include <algorithm>
#include <vector>
#include <string>
#include <utility>
//...
std::vector<std::pair<std::string, int>> names_scores_vec;
// ... populate names_scores_vec...
// lambda for sorting, change to > for descending order
auto sort_by_scores = [](const std::pair<string,int>& _lhs, 
    const std::pair<string,int>& _rhs) { return _lhs.second < _rhs.second; };
std::sort(names_scores_vec.begin(), names_scores_vec.end(), sort_by_scores);
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>

// Fill the zipped vector with pairs consisting of the
// corresponding elements of a and b. (This assumes 
// that the vectors have equal length)
template <typename A, typename B>
void zip(
    const std::vector<A> &a, 
    const std::vector<B> &b, 
    std::vector<std::pair<A,B>> &zipped)
{
    for(size_t i=0; i<a.size(); ++i)
    {
        zipped.push_back(std::make_pair(a[i], b[i]));
    }
}

// Write the first and second element of the pairs in 
// the given zipped vector into a and b. (This assumes 
// that the vectors have equal length)
template <typename A, typename B>
void unzip(
    const std::vector<std::pair<A, B>> &zipped, 
    std::vector<A> &a, 
    std::vector<B> &b)
{
    for(size_t i=0; i<a.size(); i++)
    {
        a[i] = zipped[i].first;
        b[i] = zipped[i].second;
    }
}


int main(int argc, char* argv[])
{
    std::vector<std::string> names {"Karl", "Martin", "Paul", "Jennie"};
    std::vector<int> score {45, 5, 14, 24};

    // Zip the vectors together
    std::vector<std::pair<std::string,int>> zipped;
    zip(names, score, zipped);

    // Sort the vector of pairs
    std::sort(std::begin(zipped), std::end(zipped), 
        [&](const auto& a, const auto& b)
        {
            return a.second > b.second;
        });

    // Write the sorted pairs back to the original vectors
    unzip(zipped, names, score);

    for(size_t i=0; i<names.size(); i++)
    {
        std::cout << names[i] << " : " << score[i] << std::endl;
    }
    return 0;
}
#包括
#包括
#包括
#包括
//...
std::向量名称\u分数\u向量;
// ... 填充名称\u分数\u向量。。。
//lambda用于排序,更改为>用于降序
按分数自动排序=[](常数std::pair&\u lhs,
const std::pair&_rhs){return_lhs.second<_rhs.second;};
std::sort(名称\分数\向量.begin()、名称\分数\向量.end()、按分数排序);

或者,如果需要重复的键(即允许重复的名称),请使用存储,例如
std::map
std::multimap

如果无法将数据合并为成对向量或同时具有这两种属性的结构,则可以创建迭代器向量,或从0到大小1的索引。然后使用自定义比较器对其进行排序。最后,创建一个新的向量,使用迭代器或索引填充它

template<class T1, class A1, class T2, class A2>
std::vector<T1, A1> sort_by(
  std::vector<T1,A1> const& vin, std::vector<T2,A2> const& keys
){
  std::vector<std::size_t> is;
  is.reserve(vin.size());
  for (auto&& unused:keys)
    is.push_back(is.size());
  std::sort(begin(is),end(is),[&](std::size_t l, std::size_t r){
    return keys[l]<keys[r];
  });
  std::vector<T1, A1> r;
  r.reserve(vin.size());
  for(std::size_t i:is)
    r.push_back(vin[i]);
  return r;
}
模板
std::向量排序依据(
标准::向量常量和vin,标准::向量常量和键
){
std::向量是;
是保留(vin.size());
用于(自动和未使用:键)
is.push_back(is.size());
标准::排序(开始(is),结束(is),[&](标准::大小,标准::大小){

返回键[l]正如其他答案中所建议的:将每个人的姓名和分数结合起来可能是最简单的解决方案

一般来说,这可以通过有时被称为“压缩”的操作来实现:将两个向量组合成一对向量,以及相应的“解压缩”

一般来说,这可能如下所示:

#include <algorithm>
#include <vector>
#include <string>
#include <utility>
//...
std::vector<std::pair<std::string, int>> names_scores_vec;
// ... populate names_scores_vec...
// lambda for sorting, change to > for descending order
auto sort_by_scores = [](const std::pair<string,int>& _lhs, 
    const std::pair<string,int>& _rhs) { return _lhs.second < _rhs.second; };
std::sort(names_scores_vec.begin(), names_scores_vec.end(), sort_by_scores);
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>

// Fill the zipped vector with pairs consisting of the
// corresponding elements of a and b. (This assumes 
// that the vectors have equal length)
template <typename A, typename B>
void zip(
    const std::vector<A> &a, 
    const std::vector<B> &b, 
    std::vector<std::pair<A,B>> &zipped)
{
    for(size_t i=0; i<a.size(); ++i)
    {
        zipped.push_back(std::make_pair(a[i], b[i]));
    }
}

// Write the first and second element of the pairs in 
// the given zipped vector into a and b. (This assumes 
// that the vectors have equal length)
template <typename A, typename B>
void unzip(
    const std::vector<std::pair<A, B>> &zipped, 
    std::vector<A> &a, 
    std::vector<B> &b)
{
    for(size_t i=0; i<a.size(); i++)
    {
        a[i] = zipped[i].first;
        b[i] = zipped[i].second;
    }
}


int main(int argc, char* argv[])
{
    std::vector<std::string> names {"Karl", "Martin", "Paul", "Jennie"};
    std::vector<int> score {45, 5, 14, 24};

    // Zip the vectors together
    std::vector<std::pair<std::string,int>> zipped;
    zip(names, score, zipped);

    // Sort the vector of pairs
    std::sort(std::begin(zipped), std::end(zipped), 
        [&](const auto& a, const auto& b)
        {
            return a.second > b.second;
        });

    // Write the sorted pairs back to the original vectors
    unzip(zipped, names, score);

    for(size_t i=0; i<names.size(); i++)
    {
        std::cout << names[i] << " : " << score[i] << std::endl;
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
//用包含以下内容的对填充压缩向量:
//a和b的相应元素。(假设
//向量长度相等)
模板
空拉链(
常数std::向量&a,
const std::vector&b,
std::vector(压缩)
{

对于(size_t i=0;i这不能通过自定义迭代器类型完成吗

编辑:

我认为最简单的形式是——根据第一个向量对一对向量进行排序——是有一个迭代器,它的函数(如解引用、下标、成员访问和相等以及排序比较)将调用第一个迭代器上的对应函数,所有其他函数(复制、算术、交换等)作用于两个迭代器

template <typename Driver, typename Passenger>
struct duo_iterator { . . . };

template <typename D, typename P>
auto make_duo_iterator(D d, P p) -> duo_iterator<D, P> { . . . }

sort(make_duo_iterator(begin(v1), begin(v2)),
     make_duo_iterator(end(v1), end(v2)));
模板
结构duo_迭代器{…};
模板
自动生成双迭代器(dd,pp)->双迭代器{…}
排序(生成迭代器(开始(v1),开始(v2)),
制作迭代器(end(v1),end(v2));
迭代器可以扩展为
多个迭代器
,以使用任何重新排序算法,指向任意数量的额外搭载序列。
这可能是一个有趣的小项目,也可能是在Boost或其他地方已经存在的类似项目

编辑2:

忘记上面的内容。
Eric Niebler有一个
视图::zip
包装器,“给定N个范围,返回一个新的范围,其中Mth元素是对所有N个范围的Mth元素调用make_tuple的结果。”

在元组的第一个元素上使用谓词对范围进行排序可能就可以了。

很多人问了这个问题,但没有人给出满意的答案。下面是一个std::sort helper,它可以同时对两个向量进行排序,只考虑一个向量的值。此解决方案基于自定义RadomIt(随机迭代器),直接对原始向量数据进行操作,无需临时拷贝、结构重新排列或附加索引:

namespace std {

namespace sort_helper {

template <typename _Data, typename _Order>
struct value_reference_t;

template <typename _Data, typename _Order>
struct value_t {
    _Data data;
    _Order val;
    inline value_t(_Data _data, _Order _val) : data(_data), val(_val) {}
    inline value_t(const value_reference_t<_Data,_Order>& rhs);
};

template <typename _Data, typename _Order>
struct value_reference_t {
    _Data* pdata;
    _Order* pval;
    value_reference_t(_Data* _itData, _Order* _itVal) : pdata(_itData), pval(_itVal) {}
    inline value_reference_t& operator = (const value_reference_t& rhs) { *pdata = *rhs.pdata; *pval = *rhs.pval; return *this; }
    inline value_reference_t& operator = (const value_t<_Data,_Order>& rhs) { *pdata = rhs.data; *pval = rhs.val; return *this; }
    inline bool operator < (const value_reference_t& rhs) { return *pval < *rhs.pval; }
};

template <typename _Data, typename _Order>
struct value_iterator_t :
    iterator< random_access_iterator_tag, value_t<_Data,_Order>, ptrdiff_t, value_t<_Data,_Order>*, value_reference_t<_Data,_Order> >
{
    _Data* itData;
    _Order* itVal;
    value_iterator_t(_Data* _itData, _Order* _itVal) : itData(_itData), itVal(_itVal) {}
    inline ptrdiff_t operator - (const value_iterator_t& rhs) const { return itVal - rhs.itVal; }
    inline value_iterator_t operator + (ptrdiff_t off) const { return value_iterator_t(itData + off, itVal + off); }
    inline value_iterator_t operator - (ptrdiff_t off) const { return value_iterator_t(itData - off, itVal - off); }
    inline value_iterator_t& operator ++ () { ++itData; ++itVal; return *this; }
    inline value_iterator_t& operator -- () { --itData; --itVal; return *this; }
    inline value_iterator_t operator ++ (int) { return value_iterator_t(itData++, itVal++); }
    inline value_iterator_t operator -- (int) { return value_iterator_t(itData--, itVal--); }
    inline value_t<_Data,_Order> operator * () const { return value_t<_Data,_Order>(*itData, *itVal); }
    inline value_reference_t<_Data,_Order> operator * () { return value_reference_t<_Data,_Order>(itData, itVal); }
    inline bool operator  < (const value_iterator_t& rhs) const { return itVal  < rhs.itVal; }
    inline bool operator == (const value_iterator_t& rhs) const { return itVal == rhs.itVal; }
    inline bool operator != (const value_iterator_t& rhs) const { return itVal != rhs.itVal; }
};

template <typename _Data, typename _Order>
inline value_t<_Data,_Order>::value_t(const value_reference_t<_Data,_Order>& rhs)
    : data(*rhs.pdata), val(*rhs.pval) {}

template <typename _Data, typename _Order>
bool operator < (const value_t<_Data,_Order>& lhs, const value_reference_t<_Data,_Order>& rhs) {
    return lhs.val < *rhs.pval; }

template <typename _Data, typename _Order>
bool operator < (const value_reference_t<_Data,_Order>& lhs, const value_t<_Data,_Order>& rhs) {
    return *lhs.pval < rhs.val; }

template <typename _Data, typename _Order>
void swap(value_reference_t<_Data,_Order> lhs, value_reference_t<_Data,_Order> rhs) {
    std::swap(*lhs.pdata, *rhs.pdata);
    std::swap(*lhs.pval, *rhs.pval); }


} // namespace sort_helper

} // namespace std

在Visual Studio 2017和GCC 5.4.0上测试的代码。

将名称和分数合并到单个结构中的替代方法是创建索引列表并排序:

 std::vector<int> indices(Names.size());
 std::iota(indices.begin(), indices.end(), 0);
 std::sort(indices.begin(), indices.end(),
           [&](int A, int B) -> bool {
                return Score[A] < Score[B];
            });
std::向量索引(Names.size());
std::iota(index.begin()、index.end()、0);
std::sort(index.begin()、index.end(),
[&](内部A,内部B)->bool{
返回分数[A]<分数[B];
});

现在,
索引
可以用来按所需的排序顺序索引
名称
分数

为什么不使用
std::vector
呢?或者至少用
int
字符串
制作一个
结构
,并有一个
向量
。或者对索引向量进行排序
std::vector>提供自定义比较器
comp(i,j):=Score[i]
。你可以看看这个。为什么结构名是复数的?它应该是带有名为people的向量的Person。因为我现在想清楚已经太晚了。修复了。如果你能举个例子,我将非常感激。不喜欢
std::iota
?不幸的是,即使在我修复了
value\u iterato中的typedef用法之后r\u t
。此外,您不应该使用以
开头的名称[A-Z]
不要将内容放入
名称空间std
。两者都会使代码的行为未定义。Thx对于查找,我现在修复了它,并在GCC上工作。给定
std::pair
具有
operator@Jasha这是一个很好的观点,但仅适用于此特定场景。对于不低于可比的
第一个
,或对于sor接下来,仍然需要一个自己的比较器,所以在这个(应该是通用的)答案中使用它可能没有错。
 std::vector<int> indices(Names.size());
 std::iota(indices.begin(), indices.end(), 0);
 std::sort(indices.begin(), indices.end(),
           [&](int A, int B) -> bool {
                return Score[A] < Score[B];
            });