お世話になります。
データをツリーに1件ずつ追加していく場合
重複箇所は1つにまとめたい(下記分かりづらいですがこんな感じです)場合、
・A−B−C ---①
・A−B−D ---②
↓
A−B−C
∟D
②追加のタイミングでA,Bと重複していることが分かれば
その下に追加データをぶらさげるようにしたいのですが、
実装方法が思い浮かばず。。ヒントで構わないのですが、②追加のタイミングで
既に生成されている①に重複箇所があることを知る方法はありますか?
分かりづらくすみません。
まさに、TreeViewの得意とするところです。
このようなものの表示のために、TreeViewがあるとっいも過言ではないと思います。
(これじゃ、解決ににらないか)
「重複箇所」という概念ではなく、表示を優先するフィールドでソートして、データ側で回せば、ハイ解決です。
そもそも、データ構造から考えてみたらいいと思います。
↑なにいっているのかわかんないや
回答を見てみましたが、意味の把握が難しいものになっていますね。
意味が通じる程度に端折るのはよいと思いますが、質問者が解決につなげ
られる程度の書き方をしてあげると、ここの掲示板も有効活用できるのでは
ないかと思います。
今少し見てみましたが、TreeView側で処理を行うのは、多少面倒な感じ
ですね。ですので、もともと、データを作成するときに作っている元データ
を元に検索するとよいのではないかと思います。
例えば、例に上がっているものです。
・A−B−C
・A−B−D
こういうものを、文字列データとして保存しているのであれば、
これにより、Aはあるか、A-Bはあるか、などを探してはどうでしょうか。
正規表現検索などを組み合わせて、行頭から探す、あいまい検索をする、
などとすると、少し簡単になるかもしれません。
もしこのようなデータを保持していないのであれば、
TTreeView1.SaveToStream によって、ツリー構造をテキスト形式で出力
できたと記憶しています。これをTStringListに読み出し、上のような
検索を行うことで、実現できるのではないかと思います。
試していませんが、ヒントになれば幸いです。
質問者さんは、そもそも重複を考えずに普通にデータをツリーに追加する場合どうしているのでしょうか。
例えば A-B-C というデータがあったら、これを分解して
1. ルートの下に A というノードを新しく作って追加する。
2. 1で作った A の下に、B というノードを新しく作って追加する。
3. 2で作った B の下に、C というノードを新しく作って追加する。
おそらくこうですよね。
重複をチェックするには、この手順を少しアレンジします。
例えばデータが A-B-D だったら、これを分解して
1. ルートの下に A というノードがあるか調べる。
あればそれを採用し、なければ新しく A を作って追加する。
2. 1で見つけたか作った A の下に、B というノードがあるか調べる。
あればそれを採用し、なければ新しく B を作って追加する。
3. 2で見つけたか作った B の下に、D というノードがあるか調べる。
あればそれを採用し、なければ新しく D を作って追加する。
こうなります。
で、タイトルと考え合わせると、この手順のうち「○○の下に××があるか調べる」ところで悩んでいるのでしょうか?
だとしたら、TTreeNodeのItem[index]プロパティで子ノードを順番に調べることができます。
// 現在のノード(current_node)の下から 'B' を探す例
next_node := nil;
for i := 0 to current_node.Count - 1 do
begin
if current_node.Item[i].Text = 'B' then
begin
next_node := current_node.Item[i]; // 見つかったのでこれを採用
break; // 残りは調べる必要なし
end;
end;
// 見つからなかったら新しく作る
if next_node = nil then
next_node := TreeView1.AddChild(current_node, 'B');
面白そうだったので、ちょっと考えてみました。
ジェネリクスを使っているので、Delphi2009以降ですが・・・(^^;
データの区切りは'-'で行っていますので、a-b-c-dのように入力してください。
階層を増やすのであれば、適宜Arrayを変更してください。
エラーチェック等はありません。
TTreeViewとTEditとTButtonを各1個配置
Dic : Array[0..3] of TDictionary<String,TObject>;
procedure TForm1.Button1Click(Sender: TObject);
var Node,aNode,pNode : TTreeNode;
i,j,k,Lv : Integer;
Str,Str2,Key : String;
begin
Node := TreeView1.TopItem;
Str := Edit1.Text;
Lv := 0;
repeat
i := Pos('-',Str);
pNode := Node;
Key := Node.Text;
while pNode.Level > 0 do begin
pNode := pNode.Parent;
Key := pNode.Text + '-' + Key;
end;
if i > 0 then begin
Str2 := Copy(Str,1,i - 1);
if not Dic[Lv].ContainsKey(Key + Str2) then begin
aNode := TreeView1.Items.AddChildFirst(Node,Str2);
Dic[Lv].Add(Key + Str2,TObject(aNode));
Node := aNode;
end
else begin
Node := TTreeNode(Dic[Lv].Items[Key + Str2]);
end;
Str := Copy(Str,i+1,Length(Str));
Inc(Lv);
end
else begin
if not Dic[Lv].ContainsKey(Key + Str) then begin
aNode := TreeView1.Items.AddChild(Node,Str);
Dic[Lv].Add(Key + Str,TObject(aNode));
end;
end;
until i = 0;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i : Integer;
begin
TreeView1.Items.Add(nil,'Root');
for i := 0 to 3 do begin
Dic[i] := TDictionary<String,TObject>.Create;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var i : Integer;
begin
for i := 0 to 3 do begin
Dic[i].Clear;
Dic[i].Free;
end;
end;
ツイート | ![]() |