如何仅对 std::vector 中的子集进行排序?
Posted
技术标签:
【中文标题】如何仅对 std::vector 中的子集进行排序?【英文标题】:How to sort only subset in std::vector? 【发布时间】:2014-02-12 17:25:03 【问题描述】:我有一个vector
的pair
s:
std::vector<std::pair<std::string, Cell::Ptr>> mCells;
我只想对元素的一个子集进行排序(在first
的string
上)。 Cell
有方法 GetSorted()
指示它是否属于该子集。
这是我最初的:
std::sort(mCells.begin(), mCells.end(),
[](std::pair<std::string, Cell::Ptr> const &a,
std::pair<std::string, Cell::Ptr> const &b)
// Only compare when both cells need to be sorted; otherwise return false
// to indicate that they are already in correct order. This keeps the
// non-marked cells at their original positions.
if (a.second->GetSorted() && b.second->GetSorted())
return a.first < b.first;
else
return false;
);
但它不起作用,因为sort
当然不会比较所有组合。有时return a.first < b.first
行甚至没有执行一次。
要定义所需的排序函数,这里有一个示例。假设元素是:
G* F C* A* D B E*
只有 *-ones 需要排序。但是,排序应该只应用于相邻的待排序元素。 (这就是为什么我有a.second->GetSorted() && b.second->GetSorted()
。)结果应该是:
G* F A* C* D B E*
所以,只有 A 和 C 是相邻的,并且是排序的。这个问题有简单的解决方案吗?
另一种解决方案导致:
A* F C* E* D B G*
目前也对我有用。因此,对所有 * 元素进行排序,而将其他元素留在原处。这似乎更容易做到。
【问题讨论】:
您打算如何识别加星标的元素进行排序? 是否可以遍历范围,识别有效范围并对它们进行排序? @DumbCoder 阅读我帖子的第三行。 @pmr 元素的数量不超过 20,所以是的(假设您正在考虑性能)。 @meaning-matters 所以你有一个对的向量,你只想对它们中的 一些 相对于彼此进行排序,而其他的保持不变?如果没有某种临时的床,我认为不会发生这种情况(即使那样,这也不是微不足道的)。如果它们完全相邻,您可以使用受限迭代器来完成,但如果它们不是...... 【参考方案1】:你需要分开查找要排序的范围和排序:
using namespace std;
auto isSorted = [](std::pair<std::string, Cell::Ptr> const &a)
return a.second->GetSorted();
auto it = begin(mCells);
const auto itEnd = end(mCells);
while (it != itEnd)
auto rangeStart = find_if(it, itEnd, isSorted);
if (rangeStart == itEnd)
break;
auto rangeEnd = find_if_not(rangeStart, itEnd, isSorted);
if (distance(rangeStart, rangeEnd) > 1)
// pair comparison should do the trick here
sort(rangeStart, rangeEnd);
it = rangeEnd;
刚刚看到您的编辑:您可以通过定义一个跳过未排序元素的自定义输入迭代器类来实现替代解决方案,然后对整个“范围”使用单个 sort() 调用。
【讨论】:
+1 自定义输入迭代器跳过未排序的元素是一个奇妙的想法。以上是关于如何仅对 std::vector 中的子集进行排序?的主要内容,如果未能解决你的问题,请参考以下文章
如何将两个 std::vector 与 std::pair 组合成一个 std::vector