2

データを保存するために、 Delphi6でDeCALのDMultiMapコンテナを使用しています。キーは、マップに数回表示される可能性のある文字列です。

特定のキーを使用してすべてのオブジェクトを適切に反復する方法を考えています。

このコードは:

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」を反復処理するための最良の方法は何ですか?

4

3 に答える 3

1

その間に私はいくつかの調査を行い、1つの解決策を見つけました。DMultiMapは順序付けられたマップ(ハッシュ値ではなく黒いツリーに基づく)であるため、同じキーを持つすべてのアイテムがグループ化され、次のコードが機能します。

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;
于 2011-02-18T11:32:09.910 に答える
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;
于 2011-02-18T11:45:28.137 に答える
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;
于 2011-02-21T09:00:57.323 に答える