如何在Delphi中正确迭代DMultiMap(贴花)的搜索结果?

如何在Delphi中正确迭代DMultiMap(贴花)的搜索结果?,delphi,decal,Delphi,Decal,我使用Delphi6中的DMultiMap容器来存储数据。键是一个可以在地图中多次出现的字符串 我想知道如何使用给定的键正确地迭代所有对象 请问该守则: function IterateOverObjects(map: DMultimap); var iter: DIterator; begin iter := map.locate(['abc']); while IterateOver(iter) do begin // do something with the valu

我使用Delphi6中的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”的最佳方式是什么呢?

与此同时,我做了一些研究,找到了一个解决方案。由于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;
函数迭代对象(map:DMultimap);
变量:分解器;
开始
iter:=map.locate(['abc']);
而iter(iter)做的是
开始
SetToKey(国际热核实验堆);
如果(getString(iter)'abc'),则中断;
设定值(iter);
//做一些有价值的事情。。。
结束;
结束;
编辑:测试版本(我更改了以前使用的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;
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;

我喜欢Linas提出的用法示例的语法,但是由于函数不能正常工作,这里有一个更正的版本。FindIn不使用快速定位并不是问题,因为它只用于迭代(DMultiMap是一个有序映射,因此具有相同键的所有项都在一起):

用法示例:

var
  iter: DIterator;

  iter := map.start; 
  while IterateOverFound(map, iter, ['abc']) do
  begin
    SetToValue(iter);
    // get value
  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;

谢谢我喜欢语法。但有两个问题:它会无限期地停留在同一个项目上,并且缺少一个SetToKey的电话。我已在您的帖子中添加了该函数的更正版本,但它只有在经过同行评审后才可见。@名称:您应该将更正版本作为单独的答案发布:)编辑的版本(使用locate的版本)无法正常工作。我使用一个包含以下值的映射进行测试:“aaa'=>0,'def'=>1,'abc'=>2,'abc'=>3,'def'=>4,'abc'=>5,'def'=>6,我得到2,3,5,1,4,6。(但我必须说,我的更正版本也不能正常工作。我将尝试更正它,并将其作为新的答案发布)这个版本是可以的。我的测试用例以前是bas:)有一件事:您不需要在findin中调用getContainer(iter),因为您有map作为参数。