複数のデータを比較するには?

解決


上海ケルベロス  2010-10-15 16:06:53  No: 39354  IP: 192.*.*.*

procedure TForm1.Button1Click(Sender: TObject);
var
  Error: Boolean;
  d1, d2, d3, d4: Integer;
begin
  d1 := 3;
  d2 := 0;
  d3 := 3;
  d4 := 3;

  Error := False;
  if (d1 > 0) and (d2 > 0) and (d1 <> d2) then
    Error := True;
  if (d1 > 0) and (d3 > 0) and (d1 <> d3) then
    Error := True;
  if (d1 > 0) and (d4 > 0) and (d1 <> d4) then
    Error := True;
  if (d2 > 0) and (d3 > 0) and (d2 <> d3) then
    Error := True;
  if (d2 > 0) and (d4 > 0) and (d2 <> d4) then
    Error := True;
  if (d3 > 0) and (d4 > 0) and (d3 <> d4) then
    Error := True;

  if Error then
    Showmessage('データが一致しません')
  else
    Showmessage('データが一致しました');
end;

例えば、上記コードのように、複数のデータを比較したい場合、
比較対象が増えると比較の式が増えてしまい困っています。
何か簡潔な式で表現出来ないものでしょうか?
Delphi 2010 WinXP です。
よろしくお願いします。

編集 削除
はな  2010-10-15 16:23:17  No: 39355  IP: 192.*.*.*

配列にして、for文等で回してチェックしたらどうですか?

編集 削除
上海ケルベロス  2010-10-15 16:28:38  No: 39356  IP: 192.*.*.*

for文で回すにしても、
1 <> 2
1 <> 3
1 <> 4
2 <> 3
2 <> 4
3 <> 4
比較なので、どう回していいものか・・・。

編集 削除
tor  2010-10-15 16:53:41  No: 39357  IP: 192.*.*.*

一応、データがd[]という配列に入っているものとして
for i := Low(d) to Pred(High(d)) do
 for j := Succ(i) to High(d) do
  if d[i] <> d[j] then...
のようにループを組めば全部の組み合わせを調べられます。
数が増えると計算量が二乗で増えていきますけれど。

一般的なやり方は、データを配列なりリストなりに格納していきつつ
すでに同じ値がリスト内にあるかどうか調べる、というものですね。
しばらく前にあった以下の質問が参考になるかと。
「TStringListの中に重複する文字列があるか検索するには?」
https://www.petitmonte.com/bbs/answers?question_id=7104

例えば値の範囲が 0..3 と限られているなら、
配列のかわりに集合型で出現の有無を覚えるようにすれば
もう少し効率よくできると思いますが。

編集 削除
D  2010-10-15 18:28:11  No: 39358  IP: 192.*.*.*

すべての値が同じという条件ならば、配列の最初の値を他の要素と比較するだけで良いのではないでしょうか。
下の例だと値が0より大きいかの判定も合わせて行っているのでiが0の時の比較が無駄ですが、まぁこのくらいなら効率に影響ないよね…ということで。

function IsEqualValue(iValue: array of Integer): Boolean;
var
  i: Integer;
begin
  Result := True;
  for i := 0 to High(iValue) do begin
    if (iValue[i] <= 0) or (iValue[0] <> iValue[i]) then begin
      Result := False;
      Exit;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  d1, d2, d3, d4: Integer;
begin
  d1 := 3;
  d2 := 0;
  d3 := 3;
  d4 := 3;

  if (IsEqualValue([d1, d2, d3, d4])) then begin
    ShowMessage('同じ');
  end else begin
    ShowMessage('違う');
  end;
end;

編集 削除
KHE00221  2010-10-15 18:54:28  No: 39359  IP: 192.*.*.*

①  小さい順にソートする
②  配列の最初から0でない数値を探す
③  ②で見つけた数と  配列の一番最後に入っている値を比較する

編集 削除
 2010-10-15 20:22:25  No: 39360  IP: 192.*.*.*

abs(a1-a2)
+ abs(a2-a3)
+ abs(a3-a4)

どれか一つでもずれてれば正の数。全部同一なら0。
要件がはっきり書いてないので、とりあえずそんだけ。

編集 削除
上海ケルベロス  2010-10-18 08:58:42  No: 39361  IP: 192.*.*.*

みなさん沢山の考え方ありがとうございます。
ただ、0を除外できていなかったり、ループ回数が無意味に増えてしまいそうなので、今回は KHE00221さんの考え方で行きたいと思います。
これなら、整数型以外の型にでも応用出来そうで、更に最短のループで処理出来そうなので。
どうも、ありがとうございました。

編集 削除
上海ケルベロス  2010-10-18 08:59:29  No: 39362  IP: 192.*.*.*

すいません。
解決押すの忘れましたw

編集 削除