C++/STL を使用して、以下と同等のことを行うにはどうすればよいですか? std::vector
値の範囲 [min, max)を入力したい。
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
シーケンスを生成するためにファンクターを使用std::generate_n
して提供できると思いますが、STL を使用してこれを行うより簡潔な方法があるかどうか疑問に思っていましたか?
C++11 には、次のものがありstd::iota
ます。
#include <vector>
#include <numeric> //std::iota
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
boost::irangeがあります:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
これを行うためにいくつかのユーティリティ関数を書くことになりました。次のように使用できます。
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
コード:
#include <vector>
#include <stdexcept>
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
if (step == IntType(0))
{
throw std::invalid_argument("step for range must be non-zero");
}
std::vector<IntType> result;
IntType i = start;
while ((step > 0) ? (i < stop) : (i > stop))
{
result.push_back(i);
i += step;
}
return result;
}
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
return range(start, stop, IntType(1));
}
template <typename IntType>
std::vector<IntType> range(IntType stop)
{
return range(IntType(0), stop, IntType(1));
}
C++11やライブラリが使えない人向け:
vector<int> x(10,0); // 0 is the starting number, 10 is the range size
transform(x.begin(),x.end(),++x.begin(),bind2nd(plus<int>(),1)); // 1 is the increment
ありますがboost::irange
、浮動小数点、負のステップを提供せず、stl コンテナーを直接初期化できません。
私のROライブラリnumeric_range
にもあります
RO でベクトルを初期化するには、次のようにします。
vector<int> V=range(10);
ドキュメントページからのカットアンドペーストの例 ( scc
- c++ スニペットエバリュエーター):
// [0,N) open-ended range. Only range from 1-arg range() is open-ended.
scc 'range(5)'
{0, 1, 2, 3, 4}
// [0,N] closed range
scc 'range(1,5)'
{1, 2, 3, 4, 5}
// floating point
scc 'range(1,5,0.5)'
{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5}
// negative step
scc 'range(10,0,-1.5)'
{10, 8.5, 7, 5.5, 4, 2.5, 1}
// any arithmetic type
scc "range('a','z')"
a b c d e f g h i j k l m n o p q r s t u v w x y z
// no need for verbose iota. (vint - vector<int>)
scc 'vint V = range(5); V'
{0, 1, 2, 3, 4}
// is lazy
scc 'auto NR = range(1,999999999999999999l); *find(NR.begin(), NR.end(), 5)'
5
// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}
// Assign 42 to 2..5
scc 'vint V=range(0,9); range(V/2, V/5) = 42; V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}
// Find (brute force algorithm) maximum of `cos(x)` in interval: `8 < x < 9`:
scc 'range(8, 9, 0.01) * cos || max'
-0.1455
// Integrate sin(x) from 0 to pi
scc 'auto d=0.001; (range(0,pi,d) * sin || add) * d'
2
// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"}; V * size || add'
9
// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99]; range(s) = "abc"; (range(s) << "XYZ") - "bc"'
aXYZ
// Hide phone number:
scc "str S=\"John Q Public (650)1234567\"; S|isdigit='X'; S"
John Q Public (XXX)XXXXXXX
私はPythonのようにそれを行う方法を知りませんが、別の代替手段は明らかにそれをループすることです:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
あなたがc ++ 11を持っているなら、クリスの答えはより良いです
C++11 を使用できない場合はstd::partial_sum
、1 から 10 までの数値を生成するために使用できます。また、0 から 9 までの数値が必要な場合は、transform を使用して 1 を引くことができます。
std::vector<int> my_data( 10, 1 );
std::partial_sum( my_data.begin(), my_data.end(), my_data.begin() );
std::transform(my_data.begin(), my_data.end(), my_data.begin(), bind2nd(std::minus<int>(), 1));