Namespaces
Variants

std::ranges::sample

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, p. ex. ranges::copy, ranges::sort, ...
Opérations séquentielles non modificatrices    
Opérations par lots
(C++17)
Opérations de recherche
Opérations séquentielles modificatrices
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Opérations de tri et connexes
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur plages partitionnées)
Opérations d'ensemble (sur plages triées)
Opérations de fusion (sur plages triées)
Opérations de tas
Opérations minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Algorithmes contraints
Tous les noms de ce menu appartiennent à l'espace de noms std::ranges
Opérations séquentielles non modificatrices
Opérations séquentielles modificatrices
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur plages triées)
       
       
Opérations d'ensemble (sur plages triées)
Opérations de tas
Opérations minimum/maximum
       
       
Opérations de permutation
Opérations de pliage
Opérations sur le stockage non initialisé
Types de retour
 
Défini dans l'en-tête <algorithm>
Signature d'appel
template< std::input_iterator I, std::sentinel_for<I> S,
          std::weakly_incrementable O, class Gen >
requires (std::forward_iterator<I> || std::random_access_iterator<O>) &&
          std::indirectly_copyable<I, O> &&
          std::uniform_random_bit_generator<std::remove_reference_t<Gen>>
O sample( I first, S last, O out, std::iter_difference_t<I> n, Gen&& gen );
(1) (depuis C++20)
template< ranges::input_range R, std::weakly_incrementable O, class Gen >
requires (ranges::forward_range<R> || std::random_access_iterator<O>) &&
          std::indirectly_copyable<ranges::iterator_t<R>, O> &&
          std::uniform_random_bit_generator<std::remove_reference_t<Gen>>
O sample( R&& r, O out, ranges::range_difference_t<R> n, Gen&& gen );
(2) (depuis C++20)
1) Sélectionne M = min(n, last - first) éléments de la séquence [firstlast) (sans remise) de sorte que chaque échantillon possible ait une probabilité d'apparition égale, et écrit ces éléments sélectionnés dans la plage commençant à out.
L'algorithme est stable (préserve l'ordre relatif des éléments sélectionnés) seulement si I modélise std::forward_iterator.
Le comportement est indéfini si out se trouve dans [firstlast).
2) Identique à (1), mais utilise r comme plage source, comme si en utilisant ranges::begin(r) comme first, et ranges::end(r) comme last.

Les entités apparentées à des fonctions décrites sur cette page sont des objets fonctions d'algorithme (informellement appelés niebloids), c'est-à-dire :

Paramètres

first, last - la paire itérateur-sentinelle définissant l'intervalle des éléments à partir desquels effectuer l'échantillonnage ( la population )
r - l'intervalle à partir duquel effectuer l'échantillonnage ( la population )
out - l'itérateur de sortie où les échantillons sont écrits
n - nombre d'échantillons à prélever
gen - le générateur de nombres aléatoires utilisé comme source d'aléatoire

Valeur de retour

Un itérateur égal à out + M , c'est-à-dire la fin de la plage d'échantillons résultante.

Complexité

Linéaire : 𝓞 ( last - first ) .

Notes

Cette fonction peut implémenter l'échantillonnage par sélection ou l'échantillonnage par réservoir .

Implémentation possible

struct sample_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S,
             std::weakly_incrementable O, class Gen>
    requires (std::forward_iterator<I> or
              std::random_access_iterator<O>) &&
              std::indirectly_copyable<I, O> &&
              std::uniform_random_bit_generator<std::remove_reference_t<Gen>>
    O operator()(I first, S last, O out, std::iter_difference_t<I> n, Gen&& gen) const
    {
        using diff_t = std::iter_difference_t<I>;
        using distrib_t = std::uniform_int_distribution<diff_t>;
        using param_t = typename distrib_t::param_type;
        distrib_t D{};
        if constexpr (std::forward_iterator<I>)
        {
            // cette branche préserve la "stabilité" des éléments échantillonnés
            auto rest{ranges::distance(first, last)};
            for (n = ranges::min(n, rest); n != 0; ++first)
                if (D(gen, param_t(0, --rest)) < n)
                {
                    *out++ = *first;
                    --n;
                }
            return out;
        }
        else
        {
            // O est un random_access_iterator
            diff_t sample_size{};
            // copie les éléments [first, first + M) vers la sortie "à accès aléatoire"
            for (; first != last && sample_size != n; ++first)
                out[sample_size++] = *first;
            // remplace certains des éléments copiés par des éléments sélectionnés aléatoirement
            for (auto pop_size{sample_size}; first != last; ++first, ++pop_size)
            {
                const auto i{D(gen, param_t{0, pop_size})};
                if (i < n)
                    out[i] = *first;
            }
            return out + sample_size;
        }
    }
    template<ranges::input_range R, std::weakly_incrementable O, class Gen>
    requires (ranges::forward_range<R> or std::random_access_iterator<O>) &&
              std::indirectly_copyable<ranges::iterator_t<R>, O> &&
              std::uniform_random_bit_generator<std::remove_reference_t<Gen>>
    O operator()(R&& r, O out, ranges::range_difference_t<R> n, Gen&& gen) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(out), n,
                       std::forward<Gen>(gen));
    }
};
inline constexpr sample_fn sample {};

Exemple

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>
void print(auto const& rem, auto const& v)
{
    std::cout << rem << " = [" << std::size(v) << "] { ";
    for (auto const& e : v)
        std::cout << e << ' ';
    std::cout << "}\n";
}
int main()
{
    const auto in = {1, 2, 3, 4, 5, 6};
    print("in", in);
    std::vector<int> out;
    const int max = in.size() + 2;
    auto gen = std::mt19937{std::random_device{}()};
    for (int n{}; n != max; ++n)
    {
        out.clear();
        std::ranges::sample(in, std::back_inserter(out), n, gen);
        std::cout << "n = " << n;
        print(", out", out);
    }
}

Sortie possible :

in = [6] { 1 2 3 4 5 6 }
n = 0, out = [0] { }
n = 1, out = [1] { 5 }
n = 2, out = [2] { 4 5 }
n = 3, out = [3] { 2 3 5 }
n = 4, out = [4] { 2 4 5 6 }
n = 5, out = [5] { 1 2 3 5 6 }
n = 6, out = [6] { 1 2 3 4 5 6 }
n = 7, out = [6] { 1 2 3 4 5 6 }

Voir aussi

réorganise aléatoirement les éléments dans une plage
(objet fonction algorithme)
(C++17)
sélectionne N éléments aléatoires d'une séquence
(modèle de fonction)