1

我想在整个向量内旋转向量的子集。要旋转的子集由另一个向量定义。

我想要实现的是:

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++;
    }
}

这行得通,但是对我来说感觉有点粗略。我想知道是否有一些巧妙的方法可以使用RangesC++20 中的库来做到这一点。像这样的东西:

// PSEUDO-CODE
auto subRange = std::ranges::views::subset(whole, part);

std::rotate(subRange.begin(), subRange.end());

我对 Ranges 库还没有很好的了解,但我认为这样的事情应该是可能的。

请注意:我希望解决方案在某种程度上使用简单std::rotate()。这样做的原因是我也想在子集上执行其他类似的功能(即std::shuffle()),所以在最终版本中执行旋转/洗牌/任何东西的实际功能将是一个变量。这是我在这里真正感兴趣的“更改子集”部分;其余的将在稍后合并。

4

0 回答 0