#include <unordered_map>
[] 연산자를 사용할 수 없다.
중복 Key를 허용하므로 map['a'] 하면 어떤 value를 리턴해야 하는지 모호하기 때문에.
find()함수를 사용하여 리턴할 경우 중복된 원소들 중 아무거나 리턴한다.
즉 라이브러리마다 어떤게 리턴될지 모름. 가장 먼저 나오는 Key의 Value가 나올 수도 있고 등등… 기준이 다 다르다.
std::equal_range 함수 사용
멀티 맵의 Key값을 인자로 받은 후 이 키에 대응되는
중복 원소들의 중 첫번째 원소의 반복자(begin) : first
중복 원소들의 중 마지막 원소의 반복자(end) : second
std::pair형태로 리턴해준다.
auto range = m.equal_range("식빵"); // Key가 식빵인 원소들의 맨 앞 반복자와 맨 끝 반복자를 pair로 리턴한다.
for (auto itr = range.first; itr != range.second; ++itr) { // "식빵" 키를 가진 원소들을 출력
std::cout << itr->first << " : " << itr->second << " " << std::endl;
}
💎출력💎
식빵 : 1
식빵 : 30
식빵 : 6
원소 탐색 반복 중 삭제 혹은 데이터 변경을 한다면, 순회 중인 iterator의 위치로 인해 오류가 발생할 수 있음
따라서
erase() 메소드가 삭제된 요소의 바로 다음 위치의 iterator를 반환등의 기법으로 관리할 필요가 있음
#include <unordered_map>
#include <vector>
#include <iostream>
#include <cstring>
#define UMAP_ITERATOR unordered_multimap<string, Contact*>::iterator
using namespace std;
typedef enum
{
NAME,
NUMBER,
BIRTHDAY,
EMAIL,
MEMO
} FIELD;
typedef struct
{
int count;
char str[20];
} RESULT;
class Contact{
public:
int id;
string* data;
Contact(int id, char* name, char* number, char* birthday, char* email, char* memo) {
this->id = id;
data = new string[5];
data[NAME] = name;
data[NUMBER] = number;
data[BIRTHDAY] = birthday;
data[EMAIL] = email;
data[MEMO] = memo;
}
~Contact(){
delete []data;
}
};
vector<unordered_multimap<string ,Contact*> > DB(5);
int id = 0;
void eraseByValue(Contact* contact){
for(int field=0;field<5;field++){
char str[20];
strcpy(str,contact->data[field].c_str());
pair<UMAP_ITERATOR,UMAP_ITERATOR> iters = DB[field].equal_range(str);
UMAP_ITERATOR iter = iters.first;
while(iter != iters.second){
if(iter->second->id == contact->id){
DB[field].erase(iter);
break;
}else iter++;
}
}
}
void eraseByValueAndField(Contact* contact, FIELD field){
char str[20];
strcpy(str,contact->data[field].c_str());
pair<UMAP_ITERATOR,UMAP_ITERATOR> iters = DB[field].equal_range(str);
UMAP_ITERATOR iter = iters.first;
while(iter != iters.second){
if(iter->second->id == contact->id){
DB[field].erase(iter);
break;
}else iter++;
}
}
void InitDB()
{
id = 0;
DB.clear();
DB.resize(5);
}
void Add(char* name, char* number, char* birthday, char* email, char* memo)
{
Contact* contact = new Contact(id++,name,number,birthday,email,memo);
DB[NAME].insert(make_pair(name,contact));
DB[NUMBER].insert(make_pair(number,contact));
DB[BIRTHDAY].insert(make_pair(birthday,contact));
DB[EMAIL].insert(make_pair(email,contact));
DB[MEMO].insert(make_pair(memo,contact));
}
int Delete(FIELD field, char* str)
{
int cnt = 0;
UMAP_ITERATOR iter = DB[field].find(str);
while(iter != DB[field].end()){
eraseByValue(iter->second);
iter = DB[field].find(str);
cnt++;
}
return cnt;
}
int Change(FIELD field, char* str, FIELD changefield, char* changestr)
{
int cnt = 0;
pair<UMAP_ITERATOR,UMAP_ITERATOR> iters = DB[field].equal_range(str);
UMAP_ITERATOR iter;
// 검색 필드와 변경 필드가 다름
if(field != changefield){
for(iter = iters.first; iter != iters.second; iter++){
cnt++;
eraseByValueAndField(iter->second,changefield);
iter->second->data[changefield] = changestr;
DB[changefield].insert(make_pair(changestr,iter->second));
}
// 검색 필드와 변경 필드가 같은 케이스
}else{
// 변경할 필요가 없는 케이스
if(strcmp(str,changestr) == 0){
cnt = DB[field].count(str);
}else{
iter = DB[field].find(str);
while(iter != DB[field].end()){
Contact* temp = iter->second;
eraseByValueAndField(iter->second,changefield);
temp->data[changefield] = changestr;
DB[changefield].insert(make_pair(changestr,temp));
iter = DB[field].find(str);
cnt++;
}
}
}
return cnt;
}
RESULT Search(FIELD field, char* str, FIELD ret_field)
{
RESULT result;
result.count = 0;
pair<UMAP_ITERATOR,UMAP_ITERATOR> iters = DB[field].equal_range(str);
UMAP_ITERATOR iter;
for(iter = iters.first; iter != iters.second; iter++){
result.count++;
strcpy(result.str,iter->second->data[ret_field].c_str());
}
return result;
}
https://cplusplus.com/reference/unordered_map/unordered_multimap/count/
https://ansohxxn.github.io/stl/map/