W sekcji algorytmów brakuje wielu interesujących algorytmów. Oryginalne zgłoszenie STL było niepełne ze stanowiska Stepanowa, a niektóre algorytmy zostały nawet usunięte. The proposal autorstwa Alexandra Stiepanowa i Menga Lee wydaje się nie zawierać algorytmu inplace_merge_unique()
lub jakiejkolwiek jego odmiany.
Jednym z potencjalnych powodów, dla których nie ma takiego algorytmu, jest to, że nie jest jasne, który element powinien zostać usunięty: ponieważ porównanie jest tylko ściśle słabym porządkiem, wybór elementu ma znaczenie. Jednym ze sposobów realizacji inplace_merge_unique()
jest
- Zastosowanie
std::remove_if()
do usunięcia elementu, który jest kopią z drugiego zakresu.
- Użyj funkcji
inplace_merge()
, aby wykonać faktyczne scalenie.
Predykat na std::remove_if()
śledziłby bieżącą pozycję w pierwszej części sekwencji, która ma zostać scalona. Poniższy kod nie jest testowany, ale coś takiego powinno zadziałać:
template <typename BiDirIt, typename Comp>
BiDirIt inplace_merge_unique(BiDirIt begin, BiDirIt middle, BiDirIt end, Comp comp) {
using reference = typename std::iterator_traits<BiDirIt>::reference;
BiDirIt result = std::remove_if(middle, end, [=](reference other) mutable -> bool {
begin = std::find_if(begin, middle, [=](reference arg)->bool {
return !comp(arg, other);
});
return begin != middle && !comp(other, *begin);
});
std::inplace_merge(begin, middle, result, comp);
return result;
}
Taki algorytm byłby łatwy do wdrożenia. Możesz łatwo upuścić elementy w kroku scalania sortowania scalonego. – kay
Nieco hackowskim sposobem naśladowania tego z doładowaniem byłoby połączenie funkcji Boost.Range 'boost :: inplace_merge' oraz' unikalnego' adaptera. To opóźniłoby 'unique' do punktu, w którym zakres jest iterowany i nie dodałoby dodatkowych N kroków. Wciąż daleki od doskonałości. – pmr
pmr, jesteś tego pewien? Wydaje mi się, że zakres będzie najpierw inplace_merged, a następnie unikalny? Ponieważ kompilator/boost nie wie, że te 2 mogą być połączone – NoSenseEtAl