2011-02-18 2 views
2

데이터를 저장하기 위해 Delphi 6과 함께 DeCAL의 DMultiMap 컨테이너를 사용하고 있습니다. 키는지도에 여러 번 나타날 수있는 문자열입니다.Delphi에서 DMultiMap (DeCAL)의 검색 결과를 올바르게 반복하는 방법은 무엇입니까?

주어진 키를 가진 모든 개체에 대해 올바르게 반복하는 방법을 궁금합니다.

윌이 코드 :

function IterateOverObjects(map: DMultimap); 
var iter: DIterator; 
begin 
    iter := map.locate(['abc']); 
    while IterateOver(iter) do 
    begin 
    // do something with the value... 
    end; 
end; 

반환 키와 'ABC'과의 모든 객체? 또는 'abc'를 키로 사용하여 첫 번째 객체에서 시작하여지도의 모든 객체를 반환합니까?

편집 : 테스트되었습니다. 'abc'를 키로 사용하여 첫 번째 객체에서 시작하여지도의 모든 객체를 반환합니다. 그렇다면 'abc'를 반복하는 가장 좋은 방법은 무엇입니까?

답변

1

편집 : 테스트 버전 (나는 그것을 빨리 사용 찾지 못하는 것을 조사하기 때문에 내가 이전에 사용 findif을 변경했습니다, 그냥 모든 항목을 통해 루프) :

EDIT2 : 내 이전 테스트가 나쁜 때문에, 제대로 작동하도록 함수를 편집했습니다. Name의 대답과 거의 비슷하게 보입니다. 그러나 잘못된 기능을 가진 사람을 혼동하지 않도록 변경했습니다.

function IterateOverFound(Map: DMultiMap; var iter: DIterator; const obj: array of const): Boolean; 
begin 
    if diIteration in iter.flags then 
    begin 
    advance(iter); 
    SetToKey(iter); 
    iter := findIn(iter, Map.finish, obj); 
    end 
    else 
    begin 
    iter := Map.locate(obj); 
    Include(iter.flags, diIteration); 
    end; 

    Result := not atEnd(iter); 
    if not result then 
    Exclude(iter.flags, diIteration); 
end; 

사용 예제 :

var 
    iter: DIterator; 

    iter := map.start; 
    while IterateOverFound(map, iter, ['abc']) do 
    begin 
    SetToValue(iter); 
    // get value 
    end; 
+0

감사합니다. 나는 구문을 좋아한다. 그러나 2 가지 문제 : 동일한 항목에 무기한 유지되며 SetToKey 호출이 누락되었습니다. 귀하의 게시물에 함수의 수정 된 버전을 추가했지만 피어 검토를 한 후에 만 ​​표시됩니다. – Name

+0

@ 이름 : 수정 된 버전을 별도의 답변으로 게시해야합니다. – jalf

+0

내 대답을 편집했습니다 – Linas

1

한편 나는 몇 가지 연구를하고 하나의 해결책을 찾았습니다.

function IterateOverObjects(map: DMultimap); 
var iter1, iter2: DIterator; 
begin 
    iter1 := map.locate(['abc']); 
    if not AtEnd(iter1) then 
    begin 
    iter2 := map.upper_bound(['abc']); 
    repeat 
     // do something with the value... 
     Advance(iter1); 
    until equals(iter1, iter2); 
    end; 
end; 

또 다른 가능성은 다음과 같습니다 :

function IterateOverObjects(map: DMultimap); 
var iter: DIterator; 
begin 
    iter := map.locate(['abc']); 
    while IterateOver(iter) do 
    begin 
    SetToKey(iter); 
    if (getString(iter) <> 'abc') then break; 
    SetToValue(iter); 
    // do something with the value... 
    end; 
end; 
DMultiMap이 (검은 나무에 아닌 해시 값을 기준으로) 정렬 된 맵이기 때문에 코드를 다음을 작동 할 수 있도록, 동일한 키를 가진 모든 항목이 그룹화되어 있습니다
1

나는의 Linas에 의해 제안 된 사용 예제의 구문을 좋아하지만, 기능이 제대로 작동하지 않기 때문에, 여기에 수정 된 버전입니다. 단지 반복하는 데 사용되는 FindIn가 빨리 찾아 사용하지 않는 사실은 문제가되지 않습니다 (같은 키를 가진 모든 항목이 함께 연결되도록 DMultiMap은 정렬 된 맵이다) :

function IterateOverFound(Map: DMultiMap; var iter: DIterator; const obj: array of const): Boolean; 
var bWasToKey: boolean; 
begin 
    if diIteration in iter.flags then 
    begin 
    advance(iter); 
    bWasToKey := diKey in iter.flags; 
    SetToKey(iter); 
    iter := DeCAL.findIn(iter, DeCAL.getContainer(iter).finish, obj); 
    if not bWasToKey then 
     SetToValue(iter); 
    end else 
    begin 
    iter := Map.locate(obj); 
    Include(iter.flags, diIteration); 
    end; 
    result := not atEnd(iter); 
    if not result then 
    Exclude(iter.flags, diIteration); 
end; 

예제 사용 :

var 
    map: DMultiMap; 
    iter: DIterator; 

map := DMultiMap.Create; 
map.putPair(['aaa', 0]); 
map.putPair(['def', 1]); 
map.putPair(['abc', 2]); 
map.putPair(['abc', 3]); 
map.putPair(['def', 4]); 
map.putPair(['abc', 5]); 
map.putPair(['def', 6]); 
iter := map.start; 
while IterateOverFound(map, iter, ['abc']) do 
begin 
    // do something with the value... 
end; 
+1

이 버전은 정상입니다. 내 테스트 케이스는 이전에 bas였다. 한 가지 : findIn에서 getContainer (iter)를 호출 할 필요가 없다. map을 매개 변수로 사용하기 때문이다. – Linas

+0

getContainer를 호출 할 필요가 없다는 좋은 점. – Name

관련 문제