Copying a vector to another according to a condition

Guys,

I have a vector that holds information about people, in which one of the fields is "state", the state they live. How can I copy all the data of people who live, for example, in texas to a new vector?
Use std::copy_if(), which can be found in the <algorithm> header. You have to define your own predicate, a predicate is a function that returns either true or false. You can either use a lambda expression or define a class with an operator()(). Here's an 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
57
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

class Person
{
	std::string first;
	std::string st;
public:
	Person() { }
	Person(const std::string& arg_first, const std::string& arg_st) :
		first(arg_first), st(arg_st) { }

	std::string first_name() const { return first; }
	std::string state() const { return st; }
};

struct Person_from_texas1
{
	bool operator()(const Person& a)
	{
		if(a.state() == "Texas") { return true; }
                else { return false; }
	}
};

int main()
{
    std::vector<Person> v;
    v.push_back(Person("Peter", "Texas"));
    v.push_back(Person("Bill", "Texas"));
    v.push_back(Person("Herbert", "Texas"));
    v.push_back(Person("John", "Ohio"));

    auto Person_from_texas2 = [](const Person& a)
    {
    	if(a.state() == "Texas") { return true; }
        else { return false; }
    };

    std::vector<Person> v_texas;

    /*Try the first one, the isolate it with a comment and try the second one*/

    std::copy_if(v.cbegin(), v.cend(), std::back_inserter(v_texas), Person_from_texas1());
    //std::copy_if(v.cbegin(), v.cend(), std::back_inserter(v_texas), Person_from_texas2);

    // should be range-based for-loop, but if you haven't seen one, it might confuse you at first.
    for(int i = 0; i < v_texas.size(); ++i)
    {
        std::cout << v_texas[i].first_name() << '\t' << v_texas[i].state() << '\n';
    }

    return 0;
}


First I need to explain std::back_inserter(), basically it calls push_back() of the container. So what std::copy_if() does is it goes through each element in v and calls the function Person_from_texas1(), pseudocode: Person_from_texas1(v[0]). If the function returns true it will put the element in v_texas.

If you compiler doesn't support C++ 11 just isolate the lambda expression in comments.
Last edited on
Topic archived. No new replies allowed.