finding unequal elements in a vector


Hello everyone

I have written a small program where I am trying to find similar elements in a struct type of vector based on some conditions. I know how to find elements based on equality but could anyone please help me how to find elements where something between them is NOT equal.

There are four struct variables in each vector element (x, a, y, z). I want to find out those elements where x, y, z are equal but 'a' is different.

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
#include <iostream>

#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

using namespace std;

struct LC_413
{
    std::string x;
    std::string a;
    std::string y;
    std::string z;

    LC_413(const std::string& x, const std::string& a, const std::string& y, const std::string& z): x(x), a(a), y(y), z(z) {}

    bool operator==(const LC_413& p) const
    {
        return x == p.x && a == p.a && y == p.y && z == p.z;
    }

    bool operator<(const LC_413& p) const
    {
        if(x < p.x) return true;
        if(x > p.x) return false;
        if(y < p.y) return true;
        if(y > p.y) return false;
        if(z < p.z) return true;
        if(z > p.z) return false;
        return false;
    }
};


int main()
{
    std::vector<LC_413> v1;
    v1.push_back(LC_413("a", "1", "a", "c"));
    v1.push_back(LC_413("a", "2", "b", "b"));
    v1.push_back(LC_413("a", "2", "a", "c"));
    v1.push_back(LC_413("b", "3", "a", "c"));
    v1.push_back(LC_413("a", "0", "b", "b"));
    v1.push_back(LC_413("b", "6", "b", "h"));
    v1.push_back(LC_413("b", "4", "b", "h"));
    v1.push_back(LC_413("b", "9", "b", "h"));
    v1.push_back(LC_413("a", "1", "a", "c"));

    std::sort(v1.begin(), v1.end());

    std::pair<std::vector<LC_413>::iterator, std::vector<LC_413>::iterator> ret;

    for(std::vector<LC_413>::iterator i = v1.begin(); i != v1.end(); i = ret.second)
    {
        std::cout << "[" << i->x << ", " << i->a << ", " << i->y << ", " << i->z << "] => ";
        ret = std::equal_range(i, v1.end(), *i);
        for(std::vector<LC_413>::iterator j = ret.first; j != ret.second; ++j)
        {
            std::cout << "[" << j->x << ", " << j->a << ", " << j->y << ", " << j->z << "]";
        }
        std::cout << '\n';
    }
}


The out put of the above program is:

1
2
3
4
[a, 1, a, c] => [a, 1, a, c][a, 2, a, c][a, 1, a, c] // this line should not contain [a, 1, a, c] twice
[a, 2, b, b] => [a, 2, b, b][a, 0, b, b]
[b, 3, a, c] => [b, 3, a, c]
[b, 6, b, h] => [b, 6, b, h][b, 4, b, h][b, 9, b, h]


Thanks
http://cplusplus.com/reference/algorithm/find_if/
http://cplusplus.com/reference/algorithm/partition/
http://cplusplus.com/reference/algorithm/unique/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// comparison functor
class XYZequal : public std::unary_function< LC_413,
                                             bool > {
public:
    XYZequal( const LC_413 & lhs ) : lhs_( lhs ) {}
    result_type operator()( const argument_type  & rhs ) const
    {
        return lhs_.x == rhs.x
            && lhs_.y == rhs.y
            && lhs_.z == rhs.z;
    }
private:
    const LC_413 & lhs_;
};

//...

LC_413 lhs;
i = std::find_if( v1.begin(), v1.end(), XYZequal( lhs ) );


This compiles but it's still not tested. Took me forever to write; I'm getting rusty!

Also, perhaps a better solution would be to use a binary comparison and bind one of the arguments.
Last edited on
Thanks moorecm :)

Yes the code you sent compiles but how do I use it in my program, specially the LC_413 lhs; i = std::find_if( v1.begin(), v1.end(), XYZequal( lhs ) ); part. Could you please explain.

Regards
I'm not sure I get what you're trying to do.

If you want to do a "for each item in v1, find the next item that this condition", you would just use the find_if inside the first for loop. This is still going to be slow with large data sets (the complexity is quadratic).
Hello moorecm

I have tried some simple '!=' and bool operators and it seems to be working fine and storing only those sets of data which has the field 'a' (of struct) uncommon in it but I dont know if that's a good idea. Please guide.

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
std::vector<LC_413> v1, v2;
vector< vector<LC_413> > v3;
bool found = false;

............
............
............

for(std::vector<LC_413>::iterator i = v1.begin(); i != v1.end(); i = ret.second)
{
	ret = std::equal_range(i, v1.end(), *i); 
		
	for(std::vector<LC_413>::iterator j = ret.first; j != ret.second; ++j)
	{	    		
	 	v2.push_back(*j);
	    		
	 	if(i->a != j->a)	// if uncommon data found
	 	{
	 		found = true;	// set to true
	 	}
        }
        	
        if(found)	// if true
        {		    	
	    	v3.push_back(v2);	// store that vector data		    	
	    	found = false;		// set again to false
	    	v2.clear();
        }
}
Topic archived. No new replies allowed.