How to find the index of a randomly selected element of an array in C++

Pages: 12

Hi all,

I am new in C++ programming. I need to randomly choose an element from an array and then find out the index of that chosen element. I coded it in Matlab as below.

state = [11 37 88 9];
msize = numel(state);
current_state = state(randperm(msize, 1));
current_state_index = find(state == current_state);


Would anyone please suggest the c++ code for that?

Thank you

Why not
1
2
current_state_index = randperm(msize, 1);
current_state = state(current_state_index);


Which becomes
1
2
current_state_index = rand() % msize;
current_state = state[current_state_index];

watch out ... matlab indexes from 1, C++ from zero, if you missed that. It won't effect what is here, but in case you were converting a bunch of it over.
Last edited on
Thank you @salem and @jonnin! I will try it.
Is the following Matlab command the same for C++?

current_state_index = find(state == current_state);


Thank you
no.

state == current_state resolves to a 0 or a 1 (boolean, false or true) in c++ if it is even a valid expression.

what exactly does the matlab do? I don't recall find (expression).
if you want to find inside a vector a single value, its
find(vector.begin(), vector.end(), value)
@jonnin, in matlab, the following command the index number corresponding to the element 'current_state'

For example if state = [11 37 88 9]; and the randomly chosen element is 37, the following command will return the index corresponding to 37 i.e. 2.

current_state_index = find(state == current_state);


Would you suggest me the code for that?

Thank you
Remember that (as @jonnin remarked) Matlab and fortran (by default) index from 1, whilst C++ indexes from 0.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


template<typename T> int index( const vector<T> &V, T value )        // returns -1 if not found, or index otherwise
{
   auto it = find( V.begin(), V.end(), value );
   return it == V.end() ? -1 : it - V.begin();
}


int main()
{
   vector<int> state = { 11, 37, 88, 9 };
   int current_state = 37;
   
   int current_state_index = index( state, current_state );
   cout << current_state_index << '\n';
}
Last edited on
@lastchance, thank you!

I need that in each run 'current_state' will be chosen randomly from "state" array (i.e. 'current_state is not fixed to 37) and then I have to find out the index number of the chosen element.

Would you please suggest a code for that?

Many thanks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;


template<typename T> int index( const vector<T> &V, T value )        // returns -1 if not found, or index otherwise
{
   auto it = find( V.begin(), V.end(), value );
   return it == V.end() ? -1 : it - V.begin();
}


int main()
{
   srand( time( 0 ) );
   vector<int> state = { 11, 37, 88, 9 };
   int current_state = state[rand()%state.size()];
   
   int current_state_index = index( state, current_state );
   cout << "Current value is " << current_state << " and is found at index " << current_state_index << '\n';
}
> 'current_state' will be chosen randomly from "state" array
> and then I have to find out the index number of the chosen element.

We do not need to do this in two steps; we can get both at once:
when we are choosing a random item, we can get also get its index number.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <utility>
#include <random>
#include <iterator>
#include <list>
#include <string>

namespace matlab
{
    // return the one based matlab index of value in range; return 0 if value is not present
    // note that one based index is unusual (and somewhat inconvenient) in C++
    template < typename RANGE, typename T >
    std::size_t find( const RANGE& range, const T& value )
    {
        std::size_t index = 1 ; // one based index (starts at one)
        for( const auto& item : range )
        {
            if( value == item ) return index ; // found it; return the index
            ++index ; // increment the index before moving to the next item
        }

        return 0 ; // value was not found
    }

    // choose a random item from a non-empty range and return a pair of values
    // pair{ the chosen item, its one based matlab index  }
    template < typename ITERATOR > auto select_from( ITERATOR begin, ITERATOR end )
    {
        static std::mt19937 rng( std::random_device{}() ) ;
        std::size_t n = std::distance( begin, end ) ; // number of items
        std::size_t index = std::uniform_int_distribution<std::size_t>( 1, n )(rng); // one based random index
        return std::make_pair( *std::next( begin, index-1 ), index ) ; // return item at that index and the index
    }

    // choose a random item from a non-empty range and return a pair of values
    // pair{ the chosen item, its one based matlab index  }
    template < typename RANGE > auto select_from( const RANGE& range )
    { return select_from( std::begin(range), std::end(range) ) ; }
}

int main()
{
    const int state[] = { 11, 37, 88, 9 } ;
    const int current_state = 37 ;
    const auto current_state_index = matlab::find( state, current_state ) ;
    std::cout << current_state_index << '\n' ; // 2

    const std::list<std::string> number_strings { "one", "two", "three", "four", "five", "six", "seven" } ;
    std::cout << matlab::find( number_strings, "five" ) << '\n' ; // 5

    auto[ ival, index_ival ] = matlab::select_from(state) ;
    std::cout << "from array state: randomly selected " << ival << " with index " << index_ival << '\n' ;

    auto[ strval, index_strval ] = matlab::select_from(number_strings) ;
    std::cout << "from list number_strings: randomly selected \"" << strval << "\" with index " << index_strval << '\n' ;
}


http://coliru.stacked-crooked.com/a/d29c69f2c6681aff
We do not need to do this in two steps; we can get both at once:
when we are choosing a random item, we can get also get its index number.

you can do that in matlab as well.
basically choose a random value between 1 and max # of items in the array (inclusive) and that number is both the index and the item, same idea. You should not pick an item then go find it again to get the index, this is doing more work and extra painful in matlab which is sluggish.
@JLBorges, thank you!

I tried to run the above code but it shows the following errors

In function 'int main()':
51:9: error: expected unqualified-id before '[' token
52:60: error: 'ival' was not declared in this scope
52:86: error: 'index_ival' was not declared in this scope
54:9: error: expected unqualified-id before '[' token
55:70: error: 'strval' was not declared in this scope
55:100: error: 'index_strval' was not declared in this scope

I'm trying to understand the code. How I can print out the randomly chosen element and its index? It seems to me this will output a constant current state (37) all time.

Please correct me if i am wrong.

This is a very simplistic way with integer elements.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
#include<iostream>
#include<vector>
#include <time.h> 

using namespace std;

int range(int f,int l)
   { return (rand() % ((l-f)+1)) + f;}
   
   
   
   vector<int> find(vector<int> v,int num)
   {
   	vector<int> ret;
   	int counter=0;;
   	for (int i=0;i<v.size();i++)
   	{
   		if (v[i]==num)
   		{
   			counter+=1;
   			ret.resize(counter);
   			ret[counter-1]=i;
   		}
   	}
   	return ret;	
   }
   
   
   
int main()
{
	 srand (time(NULL));// randomize by seed

	 vector<int> v,f;
	 int size=0;
	 int index=0;
	 int val=0;
	 for (int k=0;k<7;k++)
	 {
	 	size=range(10,20);
	 	v.clear();
	 	v.resize(size);
	 	for(int i=0;i<v.size();i++) v[i]=range(-5,15); // set a value
	 	
	 	cout<<"v ={"; // show the vector
	 		for(int i=0;i<v.size();i++) cout<<v[i]<<",";cout<<"}"<<endl;
	 		
	 		index=range(0,v.size()-1);// get one of the elements
	 		val=v[index];
	 	f=find(v,val);
	 	cout<<"  "<< val<<"  at positions ";
	 	for (int i=0;i<f.size();i++) cout<<f[i]<<",";
	 	cout<<endl;
	 	cout<<endl;
	 }
	 
	 cout<<endl;
	 cout <<"Press return to end . . ."<<endl; 
cin.get();	 
} 
> I tried to run the above code but it shows the following errors

The code uses C++17, it needs to be compiled with C++17 enabled.

See the example in the link: http://coliru.stacked-crooked.com/a/d29c69f2c6681aff
g++ -std=c++17 -O3 -Wall -Wextra -pedantic-errors -pthread main.cpp && ./a.out

@Feit,
If you are only ever going to use elements of state[] then just do as @salem c said in the very first reply to your post ... in c++ or matlab.

But are you sure that you have correctly described what you ultimately want to do?
Last edited on
Thank you @oggin and @JLBorges. I will try it.


@lastchance, as I mentioned in my question, I need to randomly choose an element from an array and then find out the index of that chosen element.

Thanks everyone!
Feit wrote:
as I mentioned in my question, I need to randomly choose an element from an array and then find out the index of that chosen element.


I think you miss the point that both salem c and JLBorges are making: you find the index of the element in order to randomly choose ... not vice versa.

You don't need to "find" the index ... because you already evaluated it in doing the choosing.

A straight forward translation to C++ using 0-based array index could be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iterator>
#include <iostream>
#include <random>

auto Rand {std::mt19937 {std::random_device {}()}};
auto randNo {std::uniform_int_distribution<size_t> {0, 9}};

int main()
{
	const int state[] {11, 37, 88, 9};
	const auto msize {std::size(state)};
	auto randNo {std::uniform_int_distribution<size_t> {0, msize - 1}};
	const auto current_state_index {randNo(Rand)};
	const auto current_state {state[current_state_index]};

	std::cout << "random state is " << current_state << " at index (0 start) " << current_state_index << '\n';
}



random state is 37 at index (0 start) 1

Last edited on
Feit wrote:
I need to randomly choose an element from an array

Matlab might be able to hand you a stack of cash without telling whom it took it from, but C++ won't.

In C++ we first create a random (but valid) index. Then we mug the cash from the element at that index.

Of course we can imitate Matlab's "feature" by encapsulating the random selection into a function that takes an array and returns a value. However, in the implementation of that function we will generate index and use it.

There is no point to use that function, if you need the index too.


What is the (Matlab) index of 42 in {3, 42, 2, 42, 42, 7}? Is it {2, 4, 5}?
Pages: 12