Custom comparator for std::map not working - c++

I experienced the following phenomenon when writing some C++ code:
I have a map looking like this:
std::map<test_struct_t*, unsigned int, cmp_by_value> testmap;
This map lies globally in my program and the struct is defined as:
struct test_struct_t {
int x; int y; int val;
bool operator<(const test_struct_t &o) const {
return x < o.x || y < o.y || val < o.val;
}
test_struct_t(int a, int b, int c) : x(a), y(b), val(c) {}
};
The custom comparator I wrote is:
struct cmp_by_value {
bool operator()(const test_struct_t *a, const test_struct_t *b) const
{
return *a < *b;
}
};
Now, in my main method I do the following:
testmap.insert({new test_struct_t(0, 0, 2 ), 6});
testmap.insert({new test_struct_t(0, 1, 2 ), 6});
testmap.insert({new test_struct_t(1, 1, 0 ), 6});
testmap.insert({new test_struct_t(1, 2, 0 ), 6});
testmap.insert({new test_struct_t(2, 1, 0 ), 6});
testmap.insert({new test_struct_t(1, 2, 1 ), 6});
testmap.insert({new test_struct_t(1, 2, 0 ), 6});
And then I print the values in the map with some format method:
std::string format(test_struct_t *e) {
std::stringstream ss;
ss << "(" << e->x << "," << e->y << ") = " << e->val;
return ss.str();
}
And in the main:
std::map<test_struct_t*, unsigned int>::iterator it;
for (it = testmap.begin(); it != testmap.end(); ++it) {
std::cout << format(it->first) << std::endl;
}
My program gives the following output:
(1,1) = 0
(1,2) = 0
(1,2) = 1
(2,1) = 0
(1,2) = 0
(0,0) = 2
(0,1) = 2
Can anyone explain to me why there is the duplicate entry "(1,2) k =0"? When I remove one of the other inserted statements, everything is fine and there is no duplicate. Any ideas?
EDIT: What I also found very interesting is that:
testmap[new test_struct_t(0, 0, 2 )] = 6;
testmap[new test_struct_t(0, 1, 2 )] = 6;
testmap[new test_struct_t(1, 1, 0 )] = 6;
testmap[new test_struct_t(1, 2, 0 )] = 6;
testmap[new test_struct_t(2, 1, 0 )] = 6;
testmap[new test_struct_t(1, 2, 1 )] = 6;
testmap[new test_struct_t(1, 2, 0 )] = 6;
Gives this:
(0,0) = 2
(1,1) = 0
(1,2) = 0
(0,1) = 2

Your operator< does not define a strict weak ordering. Try
bool operator<(const test_struct_t &o) const {
return std::tie(x,y,val)<std::tie(o.x,o.y,o.val);
}

Related

Sorting a table C++

I have a table of numbers that look like this:
2 8 4 0
3 1 0 9
1 2 3 4
5 4 14 2
I put all the numbers in an array { 2,8,4,0,3,1... }. Is there a way to sort it by the first column only using a 1D array so that it ends up like this:
1 2 3 4
2 8 4 0
3 1 0 9
5 4 14 2
I know there's a way of doing it with a 2D array, but, assuming I know the number of columns, is it possible with only a 1D array?
I'd create an array of indexes into your data, and then sort those indexes; this will save a decent number of the copies.
Your sort would then examine the value of the number at the given index.
ie for your example - indexes would be 1,2,3,4
and then sorted would read 3,1,2,4
edit: this was 1 based; the code 0 based. Makes no difference.
Essentially converting your 1d array into 2. Since the bulk of your data is still contiguous (especially for large numbers of columns) reading should still be fast.
Example code:
std::vector<int> getSortedIndexes(std::vector<int> data, int size) {
int count = data.size() / size;
std::vector<int> indexes(count);
// fill in indexes from 0 to "count" since that's the size of our vector
std::iota(indexes.begin(), indexes.end(), 0);
// don't write your own sorting implementation .... really; don't.
std::sort(indexes.begin(), indexes.end(), [data, size](int indexA, int indexB) {
return data[indexA*size] < data[indexB*size];
});
return indexes;
}
For arrays of non-user defined types it is easy to do the task using the standard C function qsort.
Here is a demonstrative program.
#include <iostream>
#include <cstdlib>
int cmp( const void *a, const void *b )
{
const int *left = static_cast<const int *>( a );
const int *right = static_cast<const int *>( b );
return ( *right < *left ) - ( *left < *right );
}
int main()
{
const size_t N = 4;
int a[N * N] =
{
2, 8, 4, 0, 3, 1, 0, 9, 1, 2, 3, 4, 5, 4, 14, 2
};
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
std::cout << a[N * i + j] << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
std::qsort( a, N, sizeof( int[N] ), cmp );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
std::cout << a[N * i + j] << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
}
The program output is
2 8 4 0
3 1 0 9
1 2 3 4
5 4 14 2
1 2 3 4
2 8 4 0
3 1 0 9
5 4 14 2
So all you need is to write the function
int cmp( const void *a, const void *b )
{
const int *left = static_cast<const int *>( a );
const int *right = static_cast<const int *>( b );
return ( *right < *left ) - ( *left < *right );
}
and add just one line in your program
std::qsort( a, N, sizeof( int[N] ), cmp );
You can use bubblesort:
void sort_by_name(int* ValueArray, int NrOfValues, int RowWidth)
{
int CycleCount = NrOfValues / RowWidth;
int temp;
(int j = 0; j < CycleCount ; j++)
{
for (int i = 1; i < (CycleCount - j); i++)
{
if(ValueArray[((i-1)*RowWidth)] > ValueArray[(i*RowWidth)])
{
for(int k = 0; k<RowWidth; k++)
{
temp = ValueArray[(i*RowWidth)+k]
ValueArray[(i*RowWidth)+k] = ValueArray[((i-1)*RowWidth)+k];
ValueArray[((i-1)*RowWidth)+k] = temp;
}
}
}
}
}
keep in mind that simply making your array 2D will be a MUCH BETTER solution
edit: variable naming

C++: generate multidimensional vector of unknown depth

I have a function in C++ (call it
"weightmatrix") that takes a vector of size n as input, which contains a series of numbers a, b, c..., and returns an n-dimensional vector made up of subvectors of size c, b, a...
That was complicated sounding. Basically, in practice it should look like this:
vector<int> vector_sizes = {2, 3, 1};
cout << "Resulting matrix: " << weightmatrix(vector_sizes); // Function takes vector of size 3
/* Returns the following 3 dimensional matrix:
{ { {0, 0},
{0, 0},
{0, 0} },
{0, 0, 0} }
*/
It's a weird one, I know. I just need to generate a vector without knowing beforehand how many dimensions it will be. Any help or advice you could throw in my way would be awesome.
Here is a solution using a template MultiVector class that returns a MultiVectorView from it's operator[].
The underlying data is stored in a plain std::vector but can be accessed with the vec[x][y][z] syntax.
There is no checking for correct usage, and only very basic functionality is implemented but it gives an idea how it could be done.
#include <iostream>
#include <vector>
template <typename T>
class MultiVector;
template <typename T>
class MultiVectorView {
public:
MultiVectorView(MultiVector<T>& vec_, int index_, int dimension_) : vec(vec_), index(index_), dimension(dimension_) {}
MultiVector<T>& vec;
int index;
int dimension;
MultiVectorView& operator[](std::size_t n_index) {
int index_multiplyer = 1;
for (int i=0; i<dimension; ++i)
index_multiplyer *= vec.dimensions[i];
index += n_index*index_multiplyer;
dimension++;
return *this;
}
operator T() {
return vec.content[index];
}
MultiVectorView& operator=(T val) {
vec.content[index] = val;
return *this;
}
};
template <typename T>
class MultiVector {
public:
MultiVector(std::vector<int> dimensions_) : dimensions(dimensions_) {
int size = dimensions[0];
for (int i = 1; i<dimensions.size(); ++i)
size *= dimensions[i];
content.resize(size);
}
MultiVectorView<T> operator[](std::size_t index) {
return MultiVectorView<T>(*this, index, 1);
}
std::vector<T> content;
std::vector<int> dimensions;
};
int main() {
std::vector<int> v = {2,3,2};
MultiVector<int> test(v);
int tmp = 0;
for (int x = 0; x < v[0]; ++x)
for (int y = 0; y < v[1]; ++y)
for (int z = 0; z < v[2]; ++z) {
test[x][y][z] = tmp++;
}
for (int i=0; i<test.content.size(); ++i)
std::cout << std::endl << test.content[i] << " ";
int b = test[1][2][1];
std::cout << std::endl << "b = " << b << std::endl << "test[0][1][1] = " << test[0][1][1] << std::endl;
}
I took the hint of Galik to make a small sample:
#include <cassert>
#include <iostream>
#include <vector>
template <typename ELEM>
class NDArrayT {
private:
// dimensions
std::vector<size_t> _dims;
// data
std::vector<ELEM> _data;
public:
NDArrayT(const std::vector<size_t> &dims):
_dims(dims)
{
size_t size = _dims.empty() ? 0 : 1;
for (size_t dim : _dims) size *= dim;
_data.resize(size);
}
NDArrayT(
const std::vector<size_t> &dims,
const std::vector<ELEM> &data):
NDArrayT<ELEM>(dims)
{
assert(_data.size() == data.size());
std::copy(data.begin(), data.end(), _data.begin());
}
ELEM& operator[](const std::vector<size_t> &indices)
{
size_t i = 0, j = 0;
for (size_t n = _dims.size(); j < n; ++j) {
i *= _dims[j]; i += indices[j];
}
return _data[i];
}
const ELEM& operator[](const std::vector<size_t> &indices) const
{
size_t i = 0, j = 0;
for (size_t n = _dims.size(); j < n; ++j) {
i *= _dims[j]; i += indices[j];
}
return _data[i];
}
};
using namespace std;
ostream& operator<<(ostream &out, const vector<size_t> &values)
{
const char *sep = "";
for (size_t value : values) {
out << sep << value; sep = ", ";
}
return out;
}
bool inc(vector<size_t> &indices, const vector<size_t> &dims)
{
for (size_t i = indices.size(); i--;) {
if (++indices[i] < dims[i]) return false;
indices[i] = 0;
}
return true; // overflow
}
int main()
{
// build sample data
vector<double> data(2 * 3 * 4);
for (size_t i = data.size(); i--;) data[i] = (double)i;
// build sample array
typedef NDArrayT<double> NDArrayDouble;
const vector<size_t> dims = { 2, 3, 4 };
NDArrayDouble a(dims, data);
// print sample array (check subscript)
vector<size_t> indices(dims.size(), 0);
do {
cout << "a[" << indices << "]: " << a[indices] << endl;
} while (!inc(indices, dims));
// done
return 0;
}
Compiled and tested on ideone.
Output is:
a[0, 0, 0]: 0
a[0, 0, 1]: 1
a[0, 0, 2]: 2
a[0, 0, 3]: 3
a[0, 1, 0]: 4
a[0, 1, 1]: 5
a[0, 1, 2]: 6
a[0, 1, 3]: 7
a[0, 2, 0]: 8
a[0, 2, 1]: 9
a[0, 2, 2]: 10
a[0, 2, 3]: 11
a[1, 0, 0]: 12
a[1, 0, 1]: 13
a[1, 0, 2]: 14
a[1, 0, 3]: 15
a[1, 1, 0]: 16
a[1, 1, 1]: 17
a[1, 1, 2]: 18
a[1, 1, 3]: 19
a[1, 2, 0]: 20
a[1, 2, 1]: 21
a[1, 2, 2]: 22
a[1, 2, 3]: 23
The "arithmetic" to manage multi-dimensional arrays in contiguous memory is actually quite simple. I guess, the most "revolutionary" idea of this sample is the operator[]() which uses a std::vector<size_t> to provide the indices for each dimension.
While I was writing this down, a lot of alternatives for indexing came in my mind. – There is much space for fantasy...
E.g. for linear (one-dimensional) access, a second operator[] for size_t might be provided as well.

Is there in OpenCV operation that is like op1:op2 in Matlab? [duplicate]

How can I do the equivalent of the following using C++/STL? I want to fill a std::vector with a range of values [min, max).
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I suppose I could use std::generate_n and provide a functor to generate the sequence, but I was wondering if there is a more succinct way of doing this using STL?
In C++11, there's 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 introduced a lazy version (just like Python) as part of the ranges library:
#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
}
}
There is boost::irange:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
I ended up writing some utility functions to do this. You can use them as follows:
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
The code:
#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));
}
I've been using this library for this exact purpose for years:
https://github.com/klmr/cpp11-range
Works very well and the proxies are optimized out.
for (auto i : range(1, 5))
cout << i << "\n";
for (auto u : range(0u))
if (u == 3u)
break;
else
cout << u << "\n";
for (auto c : range('a', 'd'))
cout << c << "\n";
for (auto i : range(100).step(-3))
if (i < 90)
break;
else
cout << i << "\n";
for (auto i : indices({"foo", "bar"}))
cout << i << '\n';
There is boost::irange, but it does not provide floating point, negative steps and can not directly initialize stl containers.
There is also numeric_range in my RO library
In RO, to initialize a vector:
vector<int> V=range(10);
Cut-n-paste example from doc page (scc - c++ snippet evaluator):
// [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
For those who can't use C++11 or libraries:
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
A range() function similar to below will help:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
// define range function (only once)
template <typename T>
vector <T> range(T N1, T N2) {
vector<T> numbers(N2-N1);
iota(numbers.begin(), numbers.end(), N1);
return numbers;
}
vector <int> arr = range(0, 10);
vector <int> arr2 = range(5, 8);
for (auto n : arr) { cout << n << " "; } cout << endl;
// output: 0 1 2 3 4 5 6 7 8 9
for (auto n : arr2) { cout << n << " "; } cout << endl;
// output: 5 6 7
I don't know of a way to do it like in python but another alternative is obviously to for loop through it:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
chris's answer is better though if you have c++11
If you can't use C++11, you can use std::partial_sum to generate numbers from 1 to 10. And if you need numbers from 0 to 9, you can then subtract 1 using transform:
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));
Some time ago I wrote the following _range class, which behaves like Python range (put it to the "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;
And some test code looks like the following one:
#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;
}
}
As an iterator:
#include <iostream>
class Range {
int x, y, z;
public:
Range(int x) {this->x = 0; this->y = x; this->z = 1;}
Range(int x, int y) {this->x = x; this->y = y; this->z = 1;}
Range(int x, int y, int z) {this->x = x; this->y = y; this->z = z;}
struct Iterator
{
Iterator (int val, int inc) : val{val}, inc{inc} {}
Iterator& operator++(){val+=inc; return *this;}
int operator*() const {return val;}
friend bool operator!=(const Iterator& a, const Iterator& b){return a.val < b.val;}
private:
int val, inc;
};
Iterator begin() {return Iterator(x,z);}
Iterator end() {return Iterator(y,z);}
};
int main() {
for (auto i: Range(10))
{
std::cout << i << ' '; //0 1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(1,10))
{
std::cout << i << ' '; //1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(-10,10,3))
{
std::cout << i << ' '; //-10 -7 -4 -1 2 5 8
}
return 0;
}

Is there a compact equivalent to Python range() in C++/STL

How can I do the equivalent of the following using C++/STL? I want to fill a std::vector with a range of values [min, max).
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I suppose I could use std::generate_n and provide a functor to generate the sequence, but I was wondering if there is a more succinct way of doing this using STL?
In C++11, there's 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 introduced a lazy version (just like Python) as part of the ranges library:
#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
}
}
There is boost::irange:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
I ended up writing some utility functions to do this. You can use them as follows:
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
The code:
#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));
}
I've been using this library for this exact purpose for years:
https://github.com/klmr/cpp11-range
Works very well and the proxies are optimized out.
for (auto i : range(1, 5))
cout << i << "\n";
for (auto u : range(0u))
if (u == 3u)
break;
else
cout << u << "\n";
for (auto c : range('a', 'd'))
cout << c << "\n";
for (auto i : range(100).step(-3))
if (i < 90)
break;
else
cout << i << "\n";
for (auto i : indices({"foo", "bar"}))
cout << i << '\n';
There is boost::irange, but it does not provide floating point, negative steps and can not directly initialize stl containers.
There is also numeric_range in my RO library
In RO, to initialize a vector:
vector<int> V=range(10);
Cut-n-paste example from doc page (scc - c++ snippet evaluator):
// [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
For those who can't use C++11 or libraries:
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
A range() function similar to below will help:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
// define range function (only once)
template <typename T>
vector <T> range(T N1, T N2) {
vector<T> numbers(N2-N1);
iota(numbers.begin(), numbers.end(), N1);
return numbers;
}
vector <int> arr = range(0, 10);
vector <int> arr2 = range(5, 8);
for (auto n : arr) { cout << n << " "; } cout << endl;
// output: 0 1 2 3 4 5 6 7 8 9
for (auto n : arr2) { cout << n << " "; } cout << endl;
// output: 5 6 7
I don't know of a way to do it like in python but another alternative is obviously to for loop through it:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
chris's answer is better though if you have c++11
If you can't use C++11, you can use std::partial_sum to generate numbers from 1 to 10. And if you need numbers from 0 to 9, you can then subtract 1 using transform:
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));
Some time ago I wrote the following _range class, which behaves like Python range (put it to the "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;
And some test code looks like the following one:
#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;
}
}
As an iterator:
#include <iostream>
class Range {
int x, y, z;
public:
Range(int x) {this->x = 0; this->y = x; this->z = 1;}
Range(int x, int y) {this->x = x; this->y = y; this->z = 1;}
Range(int x, int y, int z) {this->x = x; this->y = y; this->z = z;}
struct Iterator
{
Iterator (int val, int inc) : val{val}, inc{inc} {}
Iterator& operator++(){val+=inc; return *this;}
int operator*() const {return val;}
friend bool operator!=(const Iterator& a, const Iterator& b){return a.val < b.val;}
private:
int val, inc;
};
Iterator begin() {return Iterator(x,z);}
Iterator end() {return Iterator(y,z);}
};
int main() {
for (auto i: Range(10))
{
std::cout << i << ' '; //0 1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(1,10))
{
std::cout << i << ' '; //1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(-10,10,3))
{
std::cout << i << ' '; //-10 -7 -4 -1 2 5 8
}
return 0;
}

Dimension-independent loop over boost::multi_array?

Say I've got an N-dimensional boost::multi_array (of type int for simplicity), where N is known at compile time but can vary (i.e. is a non-type template parameter). Let's assume that all dimensions have equal size m.
typedef boost::multi_array<int, N> tDataArray;
boost::array<tDataArray::index, N> shape;
shape.fill(m);
tDataArray A(shape);
Now I would like to loop over all entries in A, e.g. to print them. If N was 2 for example I think I would write something like this
boost::array<tDataArray::index, 2> index;
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < m; j++ )
{
index = {{ i, j }};
cout << A ( index ) << endl;
}
}
I've used an index object to access the elements as I think this is more flexible than the []-operator here.
But how could I write this without knowing the number of dimensions N. Is there any built-in way? The documentation of multi_array is not very clear on which types of iterators exist, etc.
Or would I have to resort to some custom method with custom pointers, computing indices from the pointers, etc.? If so - any suggestions how such an algorithm could look like?
Ok, based on the Google groups discussion already mentioned in one of the comments and on one of the examples from the library itself, here is a possible solution that lets you iterate over all values in the multi-array in a single loop and offers a way to retrieve the index for each of these elements (in case this is needed for some other stuff, as in my scenario).
#include <iostream>
#include <boost/multi_array.hpp>
#include <boost/array.hpp>
const unsigned short int DIM = 3;
typedef double tValue;
typedef boost::multi_array<tValue,DIM> tArray;
typedef tArray::index tIndex;
typedef boost::array<tIndex, DIM> tIndexArray;
tIndex getIndex(const tArray& m, const tValue* requestedElement, const unsigned short int direction)
{
int offset = requestedElement - m.origin();
return(offset / m.strides()[direction] % m.shape()[direction] + m.index_bases()[direction]);
}
tIndexArray getIndexArray( const tArray& m, const tValue* requestedElement )
{
tIndexArray _index;
for ( unsigned int dir = 0; dir < DIM; dir++ )
{
_index[dir] = getIndex( m, requestedElement, dir );
}
return _index;
}
int main()
{
double* exampleData = new double[24];
for ( int i = 0; i < 24; i++ ) { exampleData[i] = i; }
tArray A( boost::extents[2][3][4] );
A.assign(exampleData,exampleData+24);
tValue* p = A.data();
tIndexArray index;
for ( int i = 0; i < A.num_elements(); i++ )
{
index = getIndexArray( A, p );
std::cout << index[0] << " " << index[1] << " " << index[2] << " value = " << A(index) << " check = " << *p << std::endl;
++p;
}
return 0;
}
The output should be
0 0 0 value = 0 check = 0
0 0 1 value = 1 check = 1
0 0 2 value = 2 check = 2
0 0 3 value = 3 check = 3
0 1 0 value = 4 check = 4
0 1 1 value = 5 check = 5
0 1 2 value = 6 check = 6
0 1 3 value = 7 check = 7
0 2 0 value = 8 check = 8
0 2 1 value = 9 check = 9
0 2 2 value = 10 check = 10
0 2 3 value = 11 check = 11
1 0 0 value = 12 check = 12
1 0 1 value = 13 check = 13
1 0 2 value = 14 check = 14
1 0 3 value = 15 check = 15
1 1 0 value = 16 check = 16
1 1 1 value = 17 check = 17
1 1 2 value = 18 check = 18
1 1 3 value = 19 check = 19
1 2 0 value = 20 check = 20
1 2 1 value = 21 check = 21
1 2 2 value = 22 check = 22
1 2 3 value = 23 check = 23
so the memory layout goes from the outer to the inner indices. Note that the getIndex function relies on the default memory layout provided by boost::multi_array. In case the array base or the storage ordering are changed, this would have to be adjusted.
There is a lack of simple boost multi array examples. So here is a very simple example of how to fill a boost multi array using indexes and how to read all the entries using a single pointer.
typedef boost::multi_array<double, 2> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][2]);
// ------> x
// | 0 2 4
// | 1 3 5
// v
// y
double value = 0;
for(index x = 0; x < 3; ++x)
for(index y = 0; y < 2; ++y)
A[x][y] = value++;
double* it = A.origin();
double* end = A.origin() + A.num_elements();
for(; it != end; ++it){
std::cout << *it << " ";
}
// -> 0 1 2 3 4 5
If you don't need the index, you can simply do:
for (unsigned int i = 0; i < A.num_elements(); i++ )
{
tValue item = A.data()[i];
std::cout << item << std::endl;
}
Based on the answers before I produced this nice overloaded version of the insertion operator for boost::multi_arrays
using namespace std;
using namespace boost::detail::multi_array;
template <typename T , unsigned long K>
ostream &operator<<( ostream &os , const boost::multi_array<T , K> &A )
{
const T* p = A.data();
for( boost::multi_array_types::size_type i = A.num_elements() ; i-- ; ++p )
{
os << "[ ";
for( boost::multi_array_types::size_type k = 0 ; k < K ; ) {
os << ( p - A.origin() ) / A.strides()[ k ] % A.shape()[ k ]
+ A.index_bases()[ k ];
if( ++k < K )
os << ", ";
}
os << " ] = " << *p << endl;
}
return os;
}
It's just a streamlined version of answer 1, except it should work with any type T that has a working operator<<. I tested like
typedef boost::multi_array<double, 3> array_type;
typedef array_type::index index;
index x = 3;
index y = 2;
index z = 3;
array_type A( boost::extents[ x ][ y ][ z ] );
// Assign values to the elements
int values = 0;
for( index i = 0 ; i < x ; ++i )
for( index j = 0 ; j < y ; ++j )
for( index k = 0 ; k < z ; ++k )
A[ i ][ j ][ k ] = values++;
// print the results
cout << A << endl;
and it seems to work:
[ 0, 0, 0 ] = 0
[ 0, 0, 1 ] = 1
[ 0, 0, 2 ] = 2
[ 0, 1, 0 ] = 3
[ 0, 1, 1 ] = 4
[ 0, 1, 2 ] = 5
[ 1, 0, 0 ] = 6
[ 1, 0, 1 ] = 7
[ 1, 0, 2 ] = 8
[ 1, 1, 0 ] = 9
[ 1, 1, 1 ] = 10
[ 1, 1, 2 ] = 11
[ 2, 0, 0 ] = 12
[ 2, 0, 1 ] = 13
[ 2, 0, 2 ] = 14
[ 2, 1, 0 ] = 15
[ 2, 1, 1 ] = 16
[ 2, 1, 2 ] = 17
Hope this is useful to somebody, and thanks a lot for the original answers: it was very useful to me.