find index from 2 vectors combined

Hello,

I am new in c++ and I am having difficulties with finding values in two vectors.
Basically, I have two constant integer vectors u and v . They have the same length.
I would like to select all the values in u and v, that respect those statements:

u>= x1 & u<= x2 & v>= x3 & v<= x4

x1, x2, x3, x4 are predefined integers.

If it can help, below is the code i use to do that in Matlab:

idx = find(u>=x1 & u<=x2 & v>=x3 & v<=x4);
A=u(idx);
B=v(idx);

But I have no idea how to translate that in c++.
Any suggestions?
Last edited on
Can you explain what your matlab program is doing? Because coming from a c++ perspective, it looks like it is either performing a bitwise and on the values or accessing the address of the values.
Something like this, maybe?

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
#include <vector>
#include <functional>
#include <stdexcept>
#include <iostream>
#include <iomanip>

std::vector<std::size_t> index_if( const std::vector<int> & u, const std::vector<int>& v,
    std::function<bool(int,int)> select )
{
    if ( u.size() != v.size() )
        throw std::logic_error( "vector size mismatch in index_if" ) ;

    std::vector<std::size_t> indices ;
    for ( std::size_t i=0; i<u.size(); ++i )
        if ( select(u[i], v[i]) )
            indices.push_back(i) ;

    return indices ;
}

int main()
{
    int uData[] = { 3,  8, 20,  50, 10,  2, 85, 23, 40,  3 } ;
    int vData[] = { 6, 40, 33, 100,  3, 40,  5, 10, 36, 10 } ;

    const std::vector<int> u(uData, uData + (sizeof(uData)/sizeof(uData[0]))) ;
    const std::vector<int> v(vData, vData + (sizeof(vData)/sizeof(vData[0]))) ;

    const int x1 = 15, x2 = 60 ;
    const int x3 = 10, x4 = 50 ;

    auto indices = index_if(u, v, [=](int a, int b)->bool 
        {return a >= x1 && a <= x2 && b >= x3 && b <= x4;}) ;

    std::cout << std::setw(5) << "U" << std::setw(5) << "V\n" ;
    for ( auto i : indices )
        std::cout << std::setw(5) << u[i] << std::setw(5) << v[i] << '\n' ;
}
Last edited on
Thanks for quick response.
Actually, I kind of changed my mind ;-). I want to select values from a third vector based on the indices from the first two vectors.

I almost managed to do it.

However something is wrong at line 35-36. When I use line 35 it works. When I use line 36 it doesn't (I mean it does not select any data although there are plenty within the statement). Any idea why? Is it something related to the negative / positive sign?

Also, I know it's bad coding (I started C++ 2 days ago), so if you have a couple of simple neat advice to improve the code, you're welcome!

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 <fstream>
#include <cstdlib>
#include <vector>

/* Declare indices and variables*/
double longitude [191880], latitude [191880];
double inboxdens [191880];
int i,j,k,l;

int main() 
{
	/* Open longitude file  and create longitude vector*/
	std::ifstream longi ( "longitude_u.txt" );
	if ( !longi ) {
		std::cout << "Unable to read longitude file\n";
		exit(1);
	}
	for ( i=0; i<191880; i++ ) {
		longi >> longitude[i];
	}
	const std::vector<double> lng(longitude, longitude + (sizeof(longitude)/sizeof(longitude[0]))) ;

	/* Open latitude file and create latitude vector*/
	std::ifstream lati ( "latitude_u.txt" );
	if ( !lati ) {
		std::cout << "Unable to read latitude file";
		exit(1);
	}
	for ( j=0; j<191880; j++ ) {
		lati >> latitude[j];
	}
	const std::vector<double> lat(latitude, latitude + (sizeof(latitude)/sizeof(latitude[0]))) ;
	
        const double lng1 = -80, lng2 = 80, lat1 = 10, lat2 = 80;
        //const double lng1 = -60, lng2 = -59.333, lat1 = 48.25, lat2 = 49.167;
	
	/* Open daily mean density file and select density inside box */
	std::ifstream dens ("meanud_u.txt");
	if (!dens) {
		std::cout << "Unable to read meanud file";
		exit(1);
	}
	for (k=0; k<191880; k++) {
                if (lng[k] >= lng1 && lng[k] <= lng2 && lat[k] >= lat1 && lat[k] <= lat2)
			dens >> inboxdens[k];
		else
			inboxdens[k]=0;
	}

	/* Save results in MaxSize.txt*/
	std::ofstream maxsize;
	maxsize.open("MaxSize.txt");
	for (i=0; q<191880; q++){
		maxsize << inboxdens[q] << std::endl;
	}
	maxsize.close();
	
	std::cin.get();
	return 0;
}
Last edited on
Only thing I will recommend is for your for-loop to have as a condition that the end of the file has not been reached.
Actually, I kind of changed my mind ;-). I want to select values from a third vector based on the indices from the first two vectors.


Since the code I posted returns a container of indices into the first and second vector that could be used to index the third vector, that would seem a rather trivial adjustment.

As for your problem, I suspect it has more to do with the loop beginning on line 44 than the values given on lines 35/36. The inboxdens array should be populated before the loop.

Based on my previous code, but untested:

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
62
63
64
65
66
67
68
69
70
71
72
73
#include <vector>
#include <functional>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <string>


template <typename T>
std::vector<std::size_t> index_if( const std::vector<T> & u, const std::vector<T>& v,
    std::function<bool(T,T)> select )
{
    if ( u.size() != v.size() )
        throw std::logic_error( "vector size mismatch in index_if" ) ;

    std::vector<std::size_t> indices ;
    for ( std::size_t i=0; i<u.size(); ++i )
        if ( select(u[i], v[i]) )
            indices.push_back(i) ;

    return indices ;
}

typedef double data_type ;

std::vector<data_type> readFile( const std::string& filename )
{
    std::vector<data_type> data ;
    std::ifstream in(filename) ;

    data_type input ;
    while ( in >> input )
        data.push_back(input) ;

    return data ;
}

void handleError(const std::string& msg)
{
    std::cout << msg << '\n' ;
    std::exit(1) ;
}

int main()
{
    std::vector<data_type> longitude = readFile( "longitude_u.txt" ) ;
    if ( longitude.size() == 0 )
        handleError("Unable to read longitude file\n") ;

    std::vector<data_type> latitude = readFile( "latitude_u.txt" ) ;
    if ( latitude.size() == 0 )
        handleError("Unable to read latitude file\n");

    std::vector<data_type> inboxdens = readFile( "meanud_u.txt" ) ;
    if ( inboxdens.size() == 0 )
        handleError("Unable to read meanud file\n") ;

    if ( longitude.size() != latitude.size() || longitude.size() != inboxdens.size() )
        handleError("Mismatch between number of data points.\n") ;

    const double lng1 = -80, lng2 = 80, lat1 = 10, lat2 = 80;

    auto indices = index_if<data_type>(longitude, latitude, 
        [=](data_type a, data_type b) 
        { return a >= lng1 && a <= lng2 && b >=lat1 && b >= lat2; }) ;


    std::ofstream filtered( "MaxSize.txt") ;
    for ( auto i : indices )
        filtered << inboxdens[i] << '\n' ; 
}




Thanks cire. It took me a bit of time to understand every lines of your code but I have learned a lot through it. It looks like I need to learn/know the c++ keywords to be able to adopt a generic programming style.
Topic archived. No new replies allowed.