【问题标题】:Sort struct vector as sub-groups将结构向量排序为子组
【发布时间】:2020-02-23 00:50:01
【问题描述】:

我有一个结构体向量,如下所示:

struct table{

int k;
int r;
int c;

}

std::vector<table> myvector;

我想根据以下标准对向量的对象进行排序:

  • 具有相同r 值的对象应放在一起(我将相同r 的累积称为“组”)。
  • 同一组内的对象应根据c 值升序排列。
  • 应根据第一个对象的c 值对组进行升序排序。

比如myvector是这样的(每一列代表一个对象):

k:  1   2   3   5   4   6
r:  3   3   3   2   3   2
c:  3   4   2   3   1   4

排序后的向量应该是这样的:

k:  4   3   1   2   5   6
r:  3   3   3   3   2   2
c:  1   2   3   4   3   4

我的解决方案是首先根据r 值对向量进行排序,以便我们将相同的r 值放在一起:

std::sort(myvector.begin(), myvector.end(), compare_r);

bool compare_r(table left, table right){return left.r < right.r;}

我们在每个组内排序:

bool compare_c(table left, table right){return left.c < right.c;}

std::vector<table>::iterator it1, it2;
it1 = myvector.begin();
it2 = it1;

int r_now = it1 -> r;

for(; it2 != myvector.end(); ++it2){

    if(it2 -> r != r_now){
        std::sort(it1, it2, compare_c);
        r_now = it2 -> r;
        it1 = it2;
    }

}

std::sort(it1, it2, compare_c);

现在myvector 变为:

k:  5   6   4   3   1   2   
r:  2   2   3   3   3   3   
c:  3   4   1   2   3   4   

最后一步是将 k = 5 & 6 的对象放在向量的后面,因为第 1 组的第 1 个 c = 3 大于第 2 组的第 1 个 c = 1(第三个标准)。我可以复制 k = 5 & 6 并删除它们,然后将它们插入到myvector 的末尾。但这似乎不是很有效。有人有更好的主意吗?

【问题讨论】:

  • 这是一个想法。先按c 排序。然后传递向量并计算每个r 的排名——基本上,首先出现r 特定值的索引;你可以把它存储在std::map&lt;int, int&gt;,比如说。然后使用std::stable_sortr 的排名进行排序(稳定排序以保留c 上的排序)
  • k,rc 之间的关系不清楚。
  • @IgorTandetnik 好主意,只是应该使用std::unordered_map

标签: c++ algorithm sorting vector


【解决方案1】:

这是@IgorTandetnik 建议的想法的可能实现:

std::vector<table> myvector;
// sort based by c
std::sort( myvector.begin(), myvector.end(), []( const auto &l, const auto &r ) {
     return l.c < r.c;
} );
std::unordered_map<int,int> ranks;
// populate ranks based on smallest (first) c
std::transform( myvector.begin(), myvector.end(), std::inserter( ranks ), []( const auto &t ) { return std::make_pair( t.r, t.c ); } );
// stable sort by ranks of r
std::stable_sort( myvector.begin(), myvector.end(), [&ranks]( const auto &l, const auto &r ) {
     return ranks[l.r] < ranks[r.r];
} );

我没有尝试编译代码,因为您没有提供 MCVE,但如果有语法错误,它应该可以工作。

【讨论】:

  • 谢谢!我认为这是一个绝妙的方法。顺便说一句,unordered_map 不仅应该包括最小的c,还应该包括r 首次出现的所有第一个`c`。
  • @ShiqiHe 因为在填充地图的时候矢量已经按c 升序排序,自然地图将填充所有r 和最小的c,如果它第一次出现。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
相关资源
最近更新 更多