영넌 개발로그
[C++ STL] algorithm) find, find_if, count, count_if, for_each, lambda 본문
container는 data를 저장하는 공간, iterator는 container 안에 있는 data를 순차적으로 모두 access할 수 있는 방법을 제공한다. 그럼 그 데이터를 읽어서 무엇을 할지에 대한 처리는?? 그런 것을 알고리즘(algorithm)이라고 한다. 이 또한 STL 라이브러리에서 제공한다. 여기서는 핵심적인 몇 가지만 다뤄보도록 하겠다.
아래 7개는 대부분의 컨테이너에 대해서 동작하며, 통일된 방법으로 사용할 수 있다.
1. find
container 자체에서 find 메소드를 제공하는 컨테이너도 있기는 한데 그렇지 않은 것들도 있다. 내가 원하는 데이터가 어디있는지 찾기 위해 사용하는 알고리즘이다. 아주 똑같아야만 찾을 수 있다.
2. find_if
find랑 비슷한데 내가 찾고자 하는 것은 어떤 조건을 만족시키는 것이다. 라는 조건을 붙일 수 있다. 조건을 만족하는 데이터를 찾는다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
class Person {
private: //데이터 은닉성 (실제 데이터와 내보내는 데이터를 다르게하고 싶을 때 사용)
string name;
int age;
public:
Person(string _name, int _age) : name(_name), age(_age) {};
bool operator== (const Person & p1) {
if ((name == p1.name) && (age == p1.age)) {
return true;
}
return false;
}
void showPerson() {
cout << "Name: " << name << ", Age: " << age << endl;
}
int getAge() { //getter
return age;
}
string getName() { //getter
return name;
}
};
bool findCondition(Person& p1) {
if (p1.getAge() == 31) {
return true;
}
return false;
}
int main() {
vector<Person> peopleDB;
peopleDB.push_back(Person("mike1", 26));
peopleDB.push_back(Person("mike2", 20));
peopleDB.push_back(Person("mike3", 31));
peopleDB.push_back(Person("mike4", 24));
peopleDB.push_back(Person("mike5", 19));
cout << "-------------------------------------" << endl;
for (auto& e : peopleDB) {
e.showPerson();
}
//1. 찾는 범위를 iterator를 이용해서 지정
//2. 찾는 값을 지정
//3. 반환값으로 iterator(point) 위치..
//auto pos = find(peopleDB.begin(), peopleDB.end(), Person("mike2",21));
auto pos = find(peopleDB.begin(), peopleDB.end(), Person("mike2",20));
if (pos == peopleDB.end()) {
cout << "Failed to find" << endl;
}
else { //success
cout << "Success: ";
(*pos).showPerson();
}
cout << "------find_if--------------------------" << endl;
//여러개 찾으려면 범위지정을 계속적으로 해주어야한다.
pos = find_if(peopleDB.begin(), peopleDB.end(), findCondition);
if (pos == peopleDB.end()) {
cout << "Failed to find" << endl;
}
else { //success
cout << "Success: ";
(*pos).showPerson();
}
return 0;
}
3. count
나와 똑같은 것이 몇 개가 있는가? 를 찾는 알고리즘이다.
4. count_if
조건을 만족하는 것의 개수를 세는 알고리즘이다. 예를 들어 어떤 그룹에서 나이가 20대인 사람은 모두 몇명인가? 와 같은 질문에 답하기 좋은 알고리즘이다.
cout << "------count--------------------------" << endl;
int cnt = count(peopleDB.begin(), peopleDB.end(), Person("mike2", 20));
cout << "Count result: " << cnt << endl;
cout << "------count_it--------------------------" << endl;
cnt = count_if(peopleDB.begin(), peopleDB.end(),
[](Person& p1) {
if (p1.getAge() > 21)
{
return true;
}
else {
return false;
}
}
);
5. for_each
컨테이너에 들어있는 모든 데이터에 대해서 어떤 함수를 일괄적으로 적용해보고 싶을 때 사용한다. iterator를 활용하여 코딩을 할 수도 있지만 별도의 알고리즘을 제공해준다.
cout << "------for_each--------------------------" << endl;
for_each(peopleDB.begin(), peopleDB.end(),
[](Person& p1) {
p1.showPerson();
}
);
6. sort
순차적으로 맞춰준다.
이런 알고리즘이 없으면 일일이 프로그래밍해서 사용해야하는데 제공해줘서 그냥 가져다 쓰면 된다.
cout << "------sort--------------------------" << endl;
sort(peopleDB.begin(), peopleDB.end(),
//p1이 p2보다 순서가 빠르다면, true를 넘겨다오
[](Person& p1, Person& p2) {
if (p1.getAge() < p2.getAge()) {
return true;
}
return false;
});
//sort 후에 vector안의 순서대로 출력
for (auto& e : peopleDB) {
e.showPerson();
}
7. lambda expression
이름이 없는 함수이다. (funtion without name)
위에 2, 4번에서 조건을 지정해줄 때 함수(bool반환)를 지정해 주는데 이런 함수는 find_if나 count_if와 같은 알고리즘이 동작할 때만 쓰이는 함수이다. 그래서 굳이 이름을 가질 필요 없이 즉석 함수로서 일회용으로 쓰고 버릴 수 있다.
//lambda expression
//[](arguments...) { }
//여러개 찾으려면 범위지정을 계속적으로 해주어야한다.
//pos = find_if(peopleDB.begin(), peopleDB.end(), findCondition);
pos = find_if(peopleDB.begin(), peopleDB.end(),
[](Person& p1) {
if (p1.getAge() == 31) {
return true;
}
return false;
}
);
'코딩 > C++' 카테고리의 다른 글
[C++ SFML] 지뢰찾기 게임 만들기 (0) | 2022.10.25 |
---|---|
[C++ STL] container map (0) | 2020.12.07 |
[C++ STL] container set 집합 (0) | 2020.12.07 |
[C++ STL] Standard template library /Container adaptor (0) | 2020.12.07 |