如何在 TList 中找到记录的索引?

How do I find the index of a record in a TList?

我正在尝试统计每个 ProductCode 在我的数据库中的使用次数。问题是,我不知道所有的代码是什么(或者可能会添加更多)。

我假设我可以使用带有值对(productCode 和计数)的 TList 来执行此操作(我试图将其视为来自 c# 的 List<> 等)

procedure myProc
type 
  TProductCodeCount = record
     productCode : string;
     count : integer;
  end;
var
  productCodes : TList<TProductCodeCount>;
  newProductCodeCount : TProductCodeCount;
  currProductCodeCount : TProductCodeCount;
  currentProductCode : string;
  productCodeIndex : integer;
begin
  productCodes :=  TList<TProductCodeCount>.Create;

  // Get my data set
  // Loop through my data set
    begin
      currentProductCode := // value from the database ;
      productCodeIndex := productCodes.indexOf(currentProductCode);
      if productCodeIndex = -1 then
      begin
        newProductCodeCount.productCode := currentProductCode;
        newProductCodeCount.count := 1;

        productCodes.Add(newProductCodeCount)
    end
    else
    begin
      currProductCodeCount := productCodes.Extract(productCodeIndex);
      currProductCodeCount.count := currProductCodeCount.count + 1'
      productCodes.Delete(productCodeIndex);
      productCodes.Add (currProductCodeCount);
    end
  end;

  // Loop through my TList
  begin
     // do something with each productCode and count.
  end
end;

这里有两个大问题。

  1. 我不确定如何编写比较代码以使 indexOf 工作(如果这对于记录类型的 TList 甚至是可能的
  2. 列表项的更新很笨拙。

如何进行比较?或者有更好的方法来完成这个吗?

您可以使用自定义比较器,您将在构建期间传递给 TList<T>

type
  TProductCodeCountComparer = class(TComparer<TProductCodeCount>)
  public
    function Compare(const Left, Right: TProductCodeCount): Integer; override;
  end;

function TProductCodeCountComparer.Compare(const Left, Right: TProductCodeCount): Integer; 
begin
  Result := CompareStr(Left.productCode, Right.productCode);
end;

var
  Comparer: IComparer<TProductCodeCount>

Comparer := TProductCodeCountComparer.Create;
productCodes :=  TList<TProductCodeCount>.Create(Comparer);

您也可以就地创建比较器

  productCodes := TList<TProductCodeCount>.Create(
    TComparer<TProductCodeCount>.Construct(
    function (const Left, Right: TProductCodeCount): Integer
      begin
        Result := CompareStr(Left.productCode, Right.productCode);
      end));

要就地编辑记录,您可以使用 TList<T>.List 属性,它可以让您直接访问基础 TList<T> 数组,并使您能够直接修改列表中的记录:

var
  productCodes: TList<TProductCodeCount>;
....
inc(productCodes.List[productCodeIndex].count);

TList<T>.List 属性 是在 XE3 中引入的,对于早期 Delphi 版本以下 class 扩展启用就地记录修改:

  TXList<T> = class(TList<T>)
  protected type
    PT = ^T;
  function GetPItem(index: Integer): PT;
  public
    property PItems[index: Integer]: PT read GetPItem;
  end;

function TXList<T>.GetPItem(index: Integer): PT;
begin
  Result := @FItems[index];
end;

var
  productCodes: TXList<TProductCodeCount>;
....
inc(productCodes.PItems[productCodeIndex].count);