2012-10-08 2 views
1

개체 쌍을 추가, 저장 및 삭제해야합니다. Person - Hobby. 모든 사람이 여러 취미를 가질 수 있으며 여러 사람이 같은 취미를 가질 수 있습니다. 그래서 멀티 맵은 좋은 컨테이너입니다, 맞죠?C++ 멀티 맵 요소 찾기 및 지우기

페어를 추가하기 전에 페어가 추가되지 않았 으면 알려주세요. 내가 볼 수 있듯이 here 표준 클래스 방법은 알지 못한다. Peter-Football이 MM에 있습니다. 따라서 쌍이 존재하면 양의 정수 (mm.begin()과 pair iterator 사이의 거리와 같음)를 반환하고 그렇지 않으면 -1을 반환하는 메서드를 작성했습니다.

그런 다음 일부 쌍을 삭제해야합니다. 내 find 메서드를 호출하면 일부 양의 정수가 반환됩니다. 나는 myMultiMap.erase(pairIndex);라고 부르지 만 어떤 이유로 짝이 지워지지 않습니다. 그게 내 문제 야. 분명히 erase 메서드는 이 아니라 iterator이 필요합니다. 질문 : 정수를 반복자로 변환하려면 어떻게해야합니까?

감사합니다.

가 UPDATE : 나는 ....

+0

커스텀'find' 메소드는 아마도 아이템이 존재 하는지를 알아 내기 위해 반복자를 사용합니다; iterator가 있으면 그것을 사용하십시오. – tmpearce

+0

@tmpearce 내 함수가 반복자를 반환하는 경우 쌍이 종료되지 않으면 어떻게 알 수 있습니까? – Kolyunya

+2

'std :: set >가 더 적절한 컨테이너가 아니겠습니까? –

답변

3

을이 c.begin() + int_value을 시도했지만 오류이 라인에 error: no match for ‘operator+’있어 아니 내가 당신의 접근 방식을 선호하는 것이 있지만, int는 거리가 질문에 begin()와 반복자 사이 인 경우, 당신은 t를 얻을 수

c.begin() + int_value 

또는

std::advance(c.begin(), int_value) 

을 사용할 수 있습니다 그는 반복자입니다. 두 번째 버전은 랜덤 액세스 반복자가 아닌 반복자에 필요합니다.

당신의 개인적인 정성 (및 프로그램의 속도)을 고려하여 반복자를 어떤 형태로든 직접 돌려 주길 권한다.

이 방법 중 하나를 해결할 수있는 많은 인터페이스가 있습니다. 나는 "오래된 C의 방법"이라고 부르는 out 매개 변수에 의해 반환 될 것이다 :

bool find_stuff(stuff, container::iterator* out_iter) { 
... 
if(found && out_iter) 
    *out_iter = found_iter; 
return found; 
} 

그것을 사용 :

container::iterator the_iter; 
if(find_stuff(the_stuff, &the_iter)) ... 

또는

if(find_stuff(the_stuff, 0)) // if you don't need the iterator 

이 관용적 C++에서 아니지만, 리누스는 그것에 만족할 것입니다.

이론적으로 소리가 가능한 두 번째 버전은 boost::optional과 같은 것을 사용하여 값을 반환합니다. 이 방법을 사용하면 값을 반환하거나 반환하지 않습니다.

boost::optional<container::iterator> find_stuff(stuff) { 
... 
if(found && out_iter) 
    return found_iter; 
return boost::none; 
} 

사용 :

boost::optional<container::iterator> found = find_stuff(the_stuff); 
if(found) { 
    do something with *found, which is the iterator. 
} 

또는

if(find_stuff(the_stuff)) ... 

셋째 가능한 솔루션 즉, std::set::insert 길을 갈 것입니다.플래그와 값으로 구성된 한 쌍을 반환 :

std::pair<bool, container::iterator> find_stuff(stuff) { 
... 
return std::make_pair(found, found_iter); 
} 

사용 :

std::pair<bool, container::iterator> found = find_stuff(the_stuff); 
if(found.first) ... 
+0

'error : 'operator'대신''c.begin() + int_value'에 오류가 있습니다. 내가 뭘 잘못하고 있니? – Kolyunya

+0

@ Kolyunya : 반복자는 임의 액세스가 아닙니다. – jpalecek

2

mulitmap<Person,Hoobby>set<pair<Person,Hobby> >에 변경을 고려하는 것은 - 당신은 당신이 지금이 문제가 발생하지 않습니다. 또는 map<Person, set<Hobby> >으로 변경하십시오. 두 옵션 모두 중복 쌍을 삽입 할 수 없습니다.

+0

구체적인 사람의 모든 취미를 찾아야합니다. 맵은 정렬 된 값을 저장하므로 더 빨리 처리 할 수 ​​있습니다. – Kolyunya

+0

내 답변을 업데이트했습니다. 두 번째 옵션은'map >'입니다. 그러면 Person의 취미에 빠르게 접근 할 수 있습니다. – PiotrNycz

+0

조언 해 주셔서 감사합니다! – Kolyunya

1

취미 (취미)와 사람 (사람) 용으로 2 세트 (다중 세트가 아닌)를 사용합니다.이 두 세트는 필터 역할을하므로 동일한 사람을 두 번 (또는 취미) 추가하지 마십시오. 이 세트에 삽입 오퍼레이션은 삽입 된 요소에 대한 반복자를 제공합니다 (또는 이미 삽입 된 경우 요소에 대한 "오른쪽"반복자). hobbies_set과 person_set에 삽입 한 두 개의 반복자가 이제 멀티 맵에서 키와 값으로 사용됩니다.

multi_map 대신 릴레이션에 세 번째 세트 (multi_set 아님)를 사용하면 확인하지 않아도됩니다. 관계를 삽입하기 전에 이미 존재하는 경우 다시 추가되지 않으며 추가되지 않습니다.

typedef std::set<Hobbie> Hobbies; 
typedef std::set<Person> Persons; 
typedef std::pair<Hobbies::iterator,bool> HobbiesInsertRes; 
typedef std::pair<Persons::iterator,bool> PersonsInsertRes; 
struct Relation { 
    Hobbies::iterator hobbieIter; 
    Persons::iterator personIter; 
    // needed operator<(left for the as an exercies for the reader); 
}; 
typedef set<Relation> Relations; 

Hobbies hobbies; 
Persons persons; 
Relations relations; 

삽입 :

HobbiesInsertRes hres = hobbies.insert(Hobbie("foo")); 
PersonsInsertRes pres = persons.insert(Person("bar")); 
relations.insert(Relation(hres.first, pres.first)); 
// adds the relation if does not exists, if it allready did exist, well you only paid the same amount of time that you would have if you would to do a check first. 

조회 :

데이터 구조체는 반복자 및 부울을 반환합니다 두 가지면에서 (이 allready이 나이 추가 된 경우라면 알려줍니다)

// for a concrete Person-Hobbie lookup use 
relations.find(Relation(Hobbie("foo"),Person("Bar"))); 

// to find all Hobbies of Person X you will need to do some work. 
// the easy way, iterate all elements of relations 
std::vector<Hobbie> hobbiesOfX; 
Persons::iterator personX = persons.find(Person("bar")); 
std::for_each(relations.begin(), relations.end(), [&hobbiesOfBar, personX](Relation r){ 
    if(r.personIter = personX) 
    hobbiesOfX.push_back(r.hobbieIter); 
}); 

// other way to lookup all hobbies of person X 
Persons::iterator personX = persons.find(Person("bar")); 
relations.lower_bound(Relation(personX,Hobbies.begin()); 
relations.upper_bound(Relation(personX,Hobbies.end()); 
// this needs operator< on Relation to be implemented in a way that does ordering on Person first, Hobbie second. 
+0

그러면 나는 구체적인 사람의 모든 취미를 찾아야 할 것입니다. M-Map은 정렬 된 값을 저장하므로 더 빨리 처리 할 수 ​​있습니다. – Kolyunya

+0

두 맵은 값이 아닌 키에서만 세트를 정렬합니다. –