列出并包含方法 [英] List and Contains method

查看:53
本文介绍了列出并包含方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个问题:从一个空列表(0个元素)开始,我要检查此列表中是否存在一个元素。如果该记录不在列表中,则我将该记录添加到列表中,否则更新列表中的元素。
我尝试编写此代码:

 程序Project1; 

{$ APPTYPE控制台}

{$ R * .res}

使用
System.SysUtils,System.Generics.Collections ,System.Generics.Defaults;

类型
TDBStats =记录
Comb:整数;
频率:整数;
结尾;
TDBStatsList = TList< TDBStats> ;;

过程Add(ODBStats:TDBStatsList; const Item:TDBStats);
var
rItem:TDBStats;
开始
rItem:=项目;
rItem.Freq:= 1;
oDBStats.Add(rItem);
结尾;

过程Update(ODBStats:TDBStatsList; const Item:TDBStats; const Index:Integer);
var
rItem:TDBStats;
开始
rItem:=项目;
Inc(rItem.Freq);
oDBStats [Index]:= rItem;
结尾;


var
oDBStats:TDBStatsList;
rDBStats:TDBStats;
myArr:整数[0..4]的数组;
iIndex1:整数;
开始
尝试
myArr [0]:= 10;
myArr [1]:= 20;
myArr [2]:= 30;
myArr [3]:= 40;
myArr [4]:= 10;

oDBStats:= TList< TDBStats> .Create;
为iIndex1尝试
:= 0到4做
开始
rDBStats.Comb:= myArr [iIndex1];
如果oDBStats.Contains(rDBStats)然后
Update(oDBStats,rDBStats,oDBStats.IndexOf(rDBStats))
否则
Add(oDBStats,rDBStats);
结尾;
//检查列表iIndex1的
:= 0到Pred(oDBStats.Count)做
Writeln(oDBStats [iIndex1] .Comb:3,oDBStats [iIndex1] .Freq:10);
最后
oDBStats.Free;
结尾;

,但E上的
:例外情况
Writeln(E.ClassName,’:``,E.Message);
结尾;
Readln;
结尾。

,并且应返回以下结果:

  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;所以第二次当我再次检查是否为freq = 0的rdbstats时,找不到它。
因为我可以解决这个问题?我需要有一个计数器,在这里我从输入中得到一个梳子,并且我想检查该梳子是否存在于列表中,这与记录的其他字段的值无关。如果我在列表中找到梳子,那么我会进行更新,增加频率字段。
感谢您的帮助。

解决方案

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



要使您的示例工作,您必须指定一个自定义比较器,该比较器仅比较记录。这是一个示例:

  oDBStats:= TList< TDBStats> .Create(TDelegatedComparer< TDBStats> .Create(
function(const Left,Right:TDBStats):整数
开始
结果:= CompareValue(Left.comb,Right.comb);
end));

此外,更新例程中存在错误。而不是增加现有值,而是增加item参数的未定义值。第一行中的更改应使其起作用:

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


i have this problem: starting from an empty list (0 elements) i want check if an element is present or not present in this list. In case this record not is present in list then i add this record to list, otherwise update element in list. I have tried writing this code:

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.

and should return this result:

10     2
20     1
30     1
40     1
50     1

but return this result:

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

I have understood about problem: when i use oDBStats.Contains(rDBStats) it control if rDBStats element is contained in list; the first time not found it and add in list; but when it is added in list i update freq field to 1; so second time when i check again being rdbstats with freq = 0 not found it. As i can solve this problem? I need to have a counter, where i get from input a "comb" and i want check if this "comb" is present in list, indipendetely from value of the other field of the record. In case i find "comb" in list, then i update, increasing freq field. Thanks for help.

解决方案

When you call Contains on a generic list, it looks if the given value is already inside the list. The value in your case is a record which consists of two fields. As you didn't specify a custom comparer, Delphi will use a default comparer which in case of a record does a binary compare. So only when two records are binary equal they will be treated as equal.

To make your example work you have to specify a custom comparer that compares only the comb field of the records. This is an example:

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

In addition you have an error in your update routine. Instead of incrementing the existing value, you are incrementing the undefined value of the item parameter. The change in the first line should make it work:

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

这篇关于列出并包含方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆