You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在指定整数范围随机选多值?寻求替代std::sample冗余实现的方案

如何在整数范围内随机选取多个值?

你当前的实现通过创建完整的整数向量再调用std::sample,但当范围极大时,这种方式会占用大量不必要的内存,完全可以优化。标准C++库中并没有直接提供sample(int first, int last, ...)或ranges::sample(int n, ...)这类直接针对整数范围的抽样函数,但我们可以基于标准工具实现更高效的版本,避免冗余内存占用:

方案1:C++20及以上——用视图生成整数范围

C++20的范围库提供了std::views::iota,可以直接生成一个整数范围的视图(不存储实际元素,仅在遍历的时候生成值),配合std::sample使用非常简洁:

#include <ranges>
#include <algorithm>
#include <random>
#include <vector>

void Sample(int first, int last, std::vector<int>* out, std::size_t n, std::mt19937* g) {
    out->clear();
    if (n == 0 || first >= last) return;
    
    auto int_range = std::views::iota(first, last);
    std::sample(int_range.begin(), int_range.end(),
                std::back_inserter(*out), n, *g);
}

方案2:自定义计数迭代器(兼容C++11及以上)

如果你的项目还不能使用C++20,可以自定义一个简单的计数迭代器,模拟整数序列的遍历,同样不需要存储完整的整数向量:

#include <iterator>
#include <algorithm>
#include <random>
#include <vector>

// 模拟整数序列的输入迭代器
struct CountingIterator {
    using value_type = int;
    using difference_type = std::ptrdiff_t;
    using pointer = const int*;
    using reference = const int&;
    using iterator_category = std::input_iterator_tag;

    int current;
    explicit CountingIterator(int val) : current(val) {}

    value_type operator*() const { return current; }
    CountingIterator& operator++() {
        ++current;
        return *this;
    }
    CountingIterator operator++(int) {
        CountingIterator temp = *this;
        ++current;
        return temp;
    }

    bool operator==(const CountingIterator& other) const {
        return current == other.current;
    }
    bool operator!=(const CountingIterator& other) const {
        return !(*this == other);
    }
};

void Sample(int first, int last, std::vector<int>* out, std::size_t n, std::mt19937* g) {
    out->clear();
    if (n == 0 || first >= last) return;
    
    std::sample(CountingIterator(first), CountingIterator(last),
                std::back_inserter(*out), n, *g);
}

方案3:小样本场景优化——直接生成不重复随机数

如果需要抽取的样本数量n远小于整数范围的大小,可以直接用随机数生成配合集合去重,避免遍历整个范围:

#include <random>
#include <vector>
#include <unordered_set>

void Sample(int first, int last, std::vector<int>* out, std::size_t n, std::mt19937* g) {
    out->clear();
    if (n == 0 || first >= last) return;
    
    const std::size_t range_size = static_cast<std::size_t>(last - first);
    if (n >= range_size) {
        // 样本数量大于等于范围大小,直接取全部元素
        for (int i = first; i < last; ++i) {
            out->push_back(i);
        }
        return;
    }

    std::uniform_int_distribution<int> dist(first, last - 1);
    std::unordered_set<int> selected;
    while (selected.size() < n) {
        selected.insert(dist(*g));
    }
    out->assign(selected.begin(), selected.end());
}

内容的提问来源于stack exchange,提问作者ALittleDiff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:15:44