在 C /STL 中是否有与 Python range() 等效的紧凑函数

新手上路,请多包涵

如何使用 C++/STL 执行以下等效操作?我想用一系列值 [min, max) 填充 std::vector

 # Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

我想我可以使用 std::generate_n 并提供一个仿函数来生成序列,但我想知道是否有更简洁的方法可以使用 STL 来做到这一点?

原文由 M-V 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 723
2 个回答

在 C++11 中,有 std::iota

 #include <vector>
#include <numeric> //std::iota

int main() {
    std::vector<int> x(10);
    std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
}

C++20 引入了惰性版本(就像 Python)作为范围库的一部分:

 #include <iostream>
#include <ranges>

namespace views = std::views;

int main() {
    for (int x : views::iota(0, 10)) {
        std::cout << x << ' '; // 0 1 2 3 4 5 6 7 8 9
    }
}

原文由 chris 发布,翻译遵循 CC BY-SA 4.0 许可协议

前段时间我写了下面的 _range 类,它的行为类似于 Python range(把它放到“range.h”中):

 #pragma once
#include <vector>
#include <cassert>

template < typename T = size_t >
class _range
{
        const T kFrom, kEnd, kStep;

    public:

        ///////////////////////////////////////////////////////////
        // Constructor
        ///////////////////////////////////////////////////////////
        //
        // INPUT:
        //      from - Starting number of the sequence.
        //      end - Generate numbers up to, but not including this number.
        //      step -  Difference between each number in the sequence.
        //
        // REMARKS:
        //      Parameters must be all positive or all negative
        //
        _range( const T from, const T end, const T step = 1 )
            : kFrom( from ), kEnd( end ), kStep( step )
        {
            assert( kStep != 0 );
            assert( ( kFrom >= 0 && kEnd > 0 && kStep > 0 ) || ( kFrom < 0 && kEnd < 0 && kStep < 0 ) );
        }

        // Default from==0, step==1
        _range( const T end )
            : kFrom( 0 ), kEnd( end ), kStep( 1 )
        {
            assert( kEnd > 0 );
        }

    public:

        class _range_iter
        {
            T fVal;
            const T kStep;
        public:
            _range_iter( const T v, const T step ) : fVal( v ), kStep( step ) {}
            operator T  () const            { return fVal; }
            operator const T & ()           { return fVal; }
            const T operator * () const     { return fVal; }
            const _range_iter & operator ++ ()  { fVal += kStep; return * this; }

            bool operator == ( const _range_iter & ri ) const
            {
                return ! operator != ( ri );
            }

            bool operator != ( const _range_iter & ri ) const
            {
                // This is a tricky part - when working with iterators
                // it checks only once for != which must be a hit to stop;
                // However, this does not work if increasing kStart by N times kSteps skips over kEnd
                return fVal < 0 ? fVal > ri.fVal : fVal < ri.fVal;
            }
        };

        const _range_iter begin()   { return _range_iter( kFrom, kStep ); }
        const _range_iter end()     { return _range_iter( kEnd, kStep ); }

    public:

        // Conversion to any vector< T >
        operator std::vector< T > ( void )
        {
            std::vector< T > retRange;
            for( T i = kFrom; i < kEnd; i += kStep )
                retRange.push_back( i );
            return retRange;    // use move semantics here
        }
};

// A helper to use pure range meaning _range< size_t >
typedef _range<>    range;

一些测试代码如下所示:

 #include "range.h"
#include <iterator>
#include <fstream>

using namespace std;

void RangeTest( void )
{
    ofstream ostr( "RangeTest.txt" );
    if( ostr.is_open() == false )
        return;

    // 1:
    ostr << "1st test:" << endl;

    vector< float > v = _range< float >( 256 );
    copy( v.begin(), v.end(), ostream_iterator< float >( ostr, ", " ) );

    // 2:
    ostr << endl << "2nd test:" << endl;

    vector< size_t >    v_size_t( range( 0, 100, 13 ) );
    for( auto a : v_size_t )
        ostr << a << ", ";

    // 3:
    ostr << endl << "3rd test:" << endl;

    auto vvv = range( 123 );    // 0..122 inclusive, with step 1
    for( auto a : vvv )
        ostr << a << ", ";

    // 4:
    ostr << endl << "4th test:" << endl;

    // Can be used in the nested loops as well
    for( auto i : _range< float >( 0, 256, 16.5 ) )
    {
        for( auto j : _range< int >( -2, -16, -3 ) )
        {
            ostr << j << ", ";
        }
        ostr << endl << i << endl;
    }

}

原文由 Boguslaw Cyganek 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题