2011-09-07 12 views
5

Używam C++ std::multimap i muszę pętli na dwa różne klucze. Czy istnieje skuteczny sposób na zrobienie tego innego niż tworzenie dwóch zakresów i przechodzenie między tymi zakresami oddzielnie?std :: multimap uzyskiwanie dwóch zakresów

ten sposób im to robić teraz:

std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range; 
std::pair<std::multimap<String, Object*>::iterator,std::multimap<String, Object*>::iterator> range2; 

// get the range of String key 
range = multimap.equal_range(key1); 
range2 = multimap.equal_range(key2); 

for (std::multimap<String, Object*>::iterator it = range.first; it != range.second; ++it) 
{ 
    ... 
} 
for (std::multimap<String, Object*>::iterator it2 = range2.first; it2 != range2.second; ++it2) 
{ 
    ... 
} 
+2

dlaczego uważasz, że to nie jest wydajne? –

+0

To jest mój pierwszy kontakt z multimapami, więc nie jestem zbyt obeznany z nimi. Będę robił dużo pracy w tych pętlach i zastanawiałem się, czy jest inna operacja, w której można uzyskać dwa zakresy w tym samym czasie lub coś takiego. –

+0

Czy możesz podać przykład klawiszy, w których klawisze nakładają się, ale nie są sobie równe? Może mój mózg jest rozmoczony, ale wygląda na to, że zrobi to prosta kontrola równości na klawiszach. To ma dla mnie więcej sensu, jeśli masz oddzielne dolne i górne granice dla każdego zapytania. –

Odpowiedz

3

Kod początek ze jest najprostsza.

Jeśli naprawdę chcesz przerobić na dwa zakresy w tej samej pętli, możesz utworzyć własny iterator, który będzie mieć dwa zakresy iteratorów, iteruje pierwszy, dopóki nie zostanie zrobiony, a następnie przełącza się na drugi. Jest to prawdopodobnie więcej kłopotów, niż jest to warte, ponieważ musisz sam wdrożyć wszystkich członków iteratora.

Edytować: Byłem overthinking to; łatwo jest zmienić dwie pętle w jedną.

for (std::multimap<String, Object*>::iterator it = range.first; it != range2.second; ++it) 
{ 
    if (it == range.second) 
    { 
     it = range2.first; 
     if (it == range2.second) 
      break; 
    } 
    ... 
} 
+0

Pomyślałem o tym również. Czy jednak te dwa klucze muszą znajdować się obok siebie, aby to zadziałało? Na przykład, jeśli mam 3 klucze i chcę zapętlić się nad 1. i 3. rokiem, to dołączę 2 z nich? A może te stwierdzenia, jeśli to naprawią? –

+1

@Kaiser, instrukcje 'if' obsługują przejście z pierwszego zakresu do drugiego. Mogą nawet być nieczynne. Jedyne, czego nie mogą * zrobić, to przecinają się; jeśli 'range2' zawiera' range.second', otrzymasz nieskończoną pętlę. –

+0

Ahh Rozumiem. Mój range2 jest statyczny, a range1 zawsze będzie inny. Nigdy nie powinny się przecinać poprawnie? Ponieważ multimap sortuje je po wstawieniu? –

3

Boost to oczywiście robi. Korzystanie z Boost.Range i jego funkcji join zapewni Ci to, czego chcesz. Aby uzyskać więcej informacji, patrz Boost Range Library: Traversing Two Ranges Sequentially.

+0

Dzięki, Boost wydaje naprawdę potężny. Niestety, moja firma jest stara i nienawidzi nowych rzeczy ... Myślę, że będą musieli zadowolić się nieskutecznością. –

+0

tym razem nie chodzi o efektywność, chodzi o wygodę –

0

Jeśli masz dostęp do C++ - 11 (Visual Studio 10+, gcc-4.5 +) i wolno go używać auto to prawdziwa perełka:

// get the range of String key 
auto range = multimap.equal_range(key1); 
auto range2 = multimap.equal_range(key2); 

for (auto it = range.first; it != range.second; ++it) 
{ 
    ... 
} 
for (auto it2 = range2.first; it2 != range2.second; ++it2) 
{ 
    ... 
} 

W każdym razie, chciałbym po prostu przetestować klucze i wykonuj tylko drugą pętlę, jeśli key2! = key1. Sprawdzanie iteratorów za każdym razem w pętli ma pewien koszt.

Std :: set_difference pierwszego zakresu od drugiego może usprawnić kod. Może std :: set_union dwa zakresy i wstawić przez back_inserter do zestawu, aby otrzymać tylko jedną kopię?

Niektóre eksperymenty mogą być w porządku. Nie zapomnij umieścić swojego pierwszego zgadywania w miksie. Może cię zaskoczyć, jeśli chodzi o szybkość. O ile zakresy są zazwyczaj bardzo długie i/lub operacja pętli jest droga, może nie być warta bólu głowy dodatkowej księgowości.

Powiązane problemy