我想在整个向量内旋转向量的子集。要旋转的子集由另一个向量定义。
我想要实现的是:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
// ???
}
auto whole = std::vector<int> {1, 2, 3, 4, 5};
auto part = std::vector<int> { 2, 3, 4 };
auto part2 = std::vector<int> {1, 5};
rotateSubset(whole, part);
// whole is now 1, 3, 4, 2, 5;
rotateSubset(whole, part2);
// whole is now 5, 3, 4, 2, 1
给定的子集保证包含在更大的整个集合中。子集可以是整体的任何子集,以任何顺序;它不必是连续的。
这是我迄今为止尝试过的:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
assert(subset.isSubsetOf(whole)); // don't worry about the implementation of this pseudo-code for now
std::rotate(subset.begin(), subset.end());
if (subset.size() == whole.size())
whole = subset;
else
{
// copy the subset vector into the whole vector in the new order
auto it = subset.cbegin();
for (auto& element : whole)
if (std::find(subset.cbegin(), subset.cend(), element) != subset.cend())
element = *it++;
}
}
这行得通,但是对我来说感觉有点粗略。我想知道是否有一些巧妙的方法可以使用Ranges
C++20 中的库来做到这一点。像这样的东西:
// PSEUDO-CODE
auto subRange = std::ranges::views::subset(whole, part);
std::rotate(subRange.begin(), subRange.end());
我对 Ranges 库还没有很好的了解,但我认为这样的事情应该是可能的。
请注意:我希望解决方案在某种程度上使用简单std::rotate()
。这样做的原因是我也想在子集上执行其他类似的功能(即std::shuffle()
),所以在最终版本中执行旋转/洗牌/任何东西的实际功能将是一个变量。这是我在这里真正感兴趣的“更改子集”部分;其余的将在稍后合并。