2012-01-14 6 views
3

私はこの問題を抱えています:空のリストから始めます(0個の要素)このリストに要素が存在するかどうかをチェックします。このレコードがリストにない場合は、このレコードをリストに追加します。そうでない場合は、リスト内のエレメントを更新します。 私はこのコードを書いて試してみました:List and Contains method

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  1 
20  1 
30  1 
40  1 
50  1 
10  1 

::私はoDBStatsを使用する場合

10  2 
20  1 
30  1 
40  1 
50  1 

が、この結果を返すにrDBStats要素がリストに含まれている場合に制御する。(rDBStats)を含む。初めてそれを発見せずにリストに追加しました。しかしそれがリストに追加されると、freqフィールドは1に更新されます。だから、再びfreq = 0のrdbstatsが見つからないことを2回目に確認します。 私はこの問題を解決できますか?私はカウンターを持っている必要があります。私は入力から "櫛"を取得し、この "櫛"がリストに存在するかどうかをチェックしたい、レコードの他のフィールドの値から無関係にチェックします。私はリストで "櫛"を見つける場合は、私は更新、freqフィールドを増加させる。 ありがとうございます。

+0

ランダムに選択したタイプ名のため、コードを読みにくいです。 'TDBStats'の代わりに' TDBStatList'を使い、 'PDBStats'の代わりに' TDBStat'を使います。 – kludg

+0

完了しましたので、より良い結果が得られることを願っています。 –

+0

'Freq'フィールド値も' Contains'メソッドでテストされます。単に 'rDBStats.Freq:= 1;' rDBStats.Comb:= myArr [iIndex1];の後の行を追加すると正しい結果が得られますが、それは一般的な解決策ではありません。あなたのリストには異なる比較者が必要です。 – kludg

答えて

6

汎用リストにContainsを呼び出すと、指定された値がすでにリスト内にあるかどうかが調べられます。あなたのケースの値は、2つのフィールドで構成されるレコードです。カスタム比較関数を指定しなかったので、Delphiはレコードの場合にバイナリ比較を行うデフォルトの比較関数を使用します。したがって、2つのレコードがバイナリの等しい場合にのみ、等しいとみなされます。

例を機能させるには、レコードのcombフィールドのみを比較するカスタム比較関数を指定する必要があります。例:

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; 
1

本当に必要なものがdictionaryなので、間違ったデータ構造になっています。

リストを使用する際の基本的な問題は、サブセットのレコードを検索することです。しかし、リストはそのために設定されていません。 TDictionary<Integer, Integer>を使って書き換えて問題を解決してください。

dictionary code example at the Embarcadero docwikiをよくお読みになることをお勧めします。

combとは、freqと呼ばれるものです。あなたがこれを行う項目を追加するには:あなたは辞書を列挙することができます

Dict := TDictionary<Integer, Integer>; 

:このような

var 
    Dict: TDictionary<Integer, Integer>; 

と作成:

if Dict.TryGetValue(Comb, Freq) then 
    Dict[Comb] := Freq+1 
else 
    Dict.Add(Comb, 1); 

を私はあなたの辞書が、このように宣言されていると仮定しています単純なfor inループを使用します。けれども

var 
    Item: TPair<Integer, Integer>; 
... 
    for Item in Dict do 
    Writeln(Item.Key:3, Item.Value:10); 

は、辞書は奇数順に列挙することを警告されます。印刷する前にソートすることをお勧めします。

各エントリに関連する詳細情報を辞書に保存する場合は、追加のフィールドをレコードに入れます。

type 
    TDictValue = record 
    Freq: Integer; 
    Field1: string; 
    Field2: TDateTime; 
    //etc. 
    end; 

あなたの辞書はTDictionary<Integer, TDictValue>になります。

+0

ありがとうございます、私はここを見て:http://docwiki.embarcadero.com/CodeSamples/en/Generics_Collections_TDictionary_(Delphi)と私が理解している例については、私は私の場合に行うことができるように理解する小さな問題があります。特に、私はそれを宣言するような型セクションですか?たとえば、私は持っている:TDBStatsList = TList と書く必要があります:TDBStatsList = TDictionary ;しかし、それは私の櫛のエラーになります。私がよく理解していれば、この「くし」は主キーを表します。私がよりよく理解できる例を挙げようとすることができます。私がtdictionaryを使うのは初めてのことです。再度、感謝します。 –

+0

ありがとう、ちょうどあなたの例を読んだ。やってみる。もう一度ありがとうございます –

+0

私は単純な2つのフィールドを使用してそのレコードTDBStatsを簡略化しました:櫛(プライマリキーとして)と汎用フィールドとしてfreq。実際のアプリケーションでは、このレコードは、このフィールドが要素の櫛を取得するたびに更新される多くのフィールドで構成されます。あなたの例を見て、私はこのフィールドをすべて追加する必要があります:Dict.TryGetValue(Comb、Freq、Field1、field2、fieldn):Dict.TryGetValue(Comb、Freq)私が投稿したサンプルコードを取ると、要素が存在するかどうかをチェックする部分だけを更新することができますか、またはTdictionaryを使用していませんか? –

関連する問題