delphi – List和Contains方法

我有这个问题:从一个空列表(0个元素)开始,我想检查一个元素是否存在于此列表中.如果列表中没有此记录,则我将此记录添加到列表中,否则更新列表中的元素.
我试过写这段代码:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,System.Generics.Collections,System.Generics.Defaults;

type
  TDBStats = record
    Comb: Integer;
    Freq: Integer;
  end;
  TDBStatsList = TList<TDBStats>;

procedure Add(ODBStats: TDBStatsList; const Item: TDBStats);
var
  rItem: TDBStats;
begin
  rItem := Item;
  rItem.Freq := 1;
  oDBStats.Add(rItem);
end;

procedure Update(ODBStats: TDBStatsList; const Item: TDBStats; const Index: Integer);
var
  rItem: TDBStats;
begin
  rItem := Item;
  Inc(rItem.Freq);
  oDBStats[Index] := rItem;
end;


var
  oDBStats: TDBStatsList;
  rDBStats: TDBStats;
  myArr: array [0..4] of integer;
  iIndex1: Integer;
begin
  try
    myArr[0] := 10;
    myArr[1] := 20;
    myArr[2] := 30;
    myArr[3] := 40;
    myArr[4] := 10;

    oDBStats := TList<TDBStats>.Create;
    try
      for iIndex1 := 0 to 4 do
      begin
        rDBStats.Comb := myArr[iIndex1];
        if oDBStats.Contains(rDBStats) then
          Update(oDBStats,rDBStats,oDBStats.IndexOf(rDBStats))
        else
          Add(oDBStats,rDBStats);
      end;
      // Check List
      for iIndex1 := 0 to Pred(oDBStats.Count) do
        Writeln(oDBStats[iIndex1].Comb:3,oDBStats[iIndex1].Freq:10);
    finally
      oDBStats.Free;
    end;

  except
    on E: Exception do
      Writeln(E.ClassName,': ',E.Message);
  end;
  Readln;
end.

并应该返回此结果:

10     2
20     1
30     1
40     1
50     1

但是返回这个结果:

10     1
20     1
30     1
40     1
50     1
10     1

我已经理解了问题:当我使用oDBStats.Contains(rDBStats)时,它控制rDBStats元素是否包含在列表中;第一次没找到它并添加到列表中;但是当它被添加到列表中时我将freq字段更新为1;所以第二次当我再次检查rdbstats时,freq = 0没找到它.
我可以解决这个问题吗?我需要一个计数器,我从输入中得到一个“梳子”,我想检查这个“梳子”是否存在于列表中,独立于记录的另一个字段的值.如果我在列表中找到“梳子”,那么我更新,增加频率字段.
感谢帮助.

解决方法

当您在通用列表上调用Contains时,它会查看给定值是否已在列表中.您的案例中的值是一个由两个字段组成的记录.由于您没有指定自定义比较器,Delphi将使用默认比较器,在记录的情况下进行二进制比较.因此,只有当两个记录是二进制相等时,它们才会被视为相等.

要使您的示例正常工作,您必须指定一个自定义比较器,仅比较记录的梳形字段.这是一个例子:

oDBStats := TList<TDBStats>.Create(TDelegatedComparer<TDBStats>.Create(
 function(const Left,Right: TDBStats): Integer
 begin
   result := CompareValue(Left.comb,Right.comb);
 end));

此外,您的更新例程中有错误.您正在递增item参数的未定义值,而不是递增现有值.第一行的更改应该使它工作:

rItem := oDBStats[Index];
  Inc(rItem.Freq);
  oDBStats[Index] := rItem;

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...