私は、それぞれの重複する要素の前にすべての一意の要素が存在するように順序付き要素のセットを分割する方法を探していますが、std::unique
は重複した要素が上書きされるため適用できません。std::partition
。このアルゴリズムpartition_unique
を呼び出すと、対応するstable_partition_unique
(つまりstable_partition
のような)も必要です。partition_uniqueとstable_partition_uniqueのアルゴリズムを実装する
partition_unique
の基本的な実装は、次のとおり
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vals {1, 1, 2, 4, 5, 5, 5, 7, 7, 9, 10};
const auto it = partition_unique(std::begin(vals), std::end(vals));
std::cout << "Unique values: ";
std::copy(std::begin(vals), it, std::ostream_iterator<int> {std::cout, " "}); // Unique values: 1 10 2 4 5 9 7
std::cout << '\n' << "Duplicate values: ";
std::copy(it, std::end(vals), std::ostream_iterator<int> {std::cout, " "}); // Duplicate values: 7 5 5 1
}
対応stable_partition_unqiue
がstd::stable_partition
とstd::partition
を交換することによって達成することができる。
#include <algorithm>
#include <iterator>
#include <unordered_set>
#include <functional>
template <typename BidirIt, typename BinaryPredicate = std::equal_to<void>>
BidirIt partition_unique(BidirIt first, BidirIt last, BinaryPredicate p = BinaryPredicate {})
{
using ValueTp = typename std::iterator_traits<BidirIt>::value_type;
std::unordered_set<ValueTp, std::hash<ValueTp>, BinaryPredicate> seen {};
seen.reserve(std::distance(first, last));
return std::partition(first, last,
[&p, &seen] (const ValueTp& value) {
return seen.insert(value).second;
});
}
ように使用することができます。
これらのアプローチの問題点は、std::unordered_set
(すべてハッシュ関数要件を追加)のすべての一意の値を不必要にバッファリングすることです。この要素は、要素のソート時には不要である必要があります。 partition_unique
の実装を考え出すのはあまり手間がかかりませんが、stable_partition_unique
の実装はかなり難しいようです。可能であれば、私はむしろimplement this myselfではないでしょう。
partition_unique
アルゴリズムとstable_ partition_unique
アルゴリズムを最適化するための既存のアルゴリズムを使用する方法はありますか?
'std :: partition()'のほとんどの実装ではおそらく動作しますが、述語は異なる引数で異なる値を返すことはできません。あなたの述語がそうであるという事実は、例えば、クラッシュする 'std :: partition()'の並列実装です。 –
@j_random_hacker 'std :: partition'は、複雑さの要求のために各値を一度検査することだけが許可されているので、これは問題ではありません。 – Daniel
それは興味深い観察です。 AFAICTこれは、 "非定数"述語(必要な相互排除を提供するためにonusが呼び出し側にある)であっても、実際には 'std :: partition()'の正しい並列実装を可能にします。 –