如何生成这样树形的字符串?

jbas 2009-10-17 12:19:55
大家好,
我写了很久都没写出这个生成树的算法,请帮一下。


function createJsonString(rs:TList):String;
begin
//这个函数怎么写,才能生成下面的字符串。

[
{
'id':'1',
'txt':'title1',
'items':[
{
'id':'2',
'txt':'title6'
},{
'id':'3',
'txt':'title4',
'items':[
{
'id':'4',
'txt':'title5'
},{
'id':'5',
'txt':'title7'
}
]
}
]
}
,{
'id':'6',
'txt':'title2'
}
,{
'id':'7',
'txt':'title3'
}
]
end;

procedure TForm1.Button2Click(Sender: TObject);
var
f_Record: PFavoritRecord;
rsList:TList;
s:String;
begin
rsList:=TList.Create;
new(f_Record);
f_Record.favTitle:='title1';
f_Record.favIsCat:='1'; //1: 表示是目录
f_Record.favCat:=''; //‘’表示是根目录
rsList.add(f_Record);

new(f_Record);
f_Record.favTitle:='title2';
f_Record.favIsCat:=''; //'' 表示是节点
f_Record.favCat:=''; //'' 表示是根结点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title3';
f_Record.favIsCat:=''; //'' 节点
f_Record.favCat:=''; //'' 根结点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title4';
f_Record.favIsCat:='1'; //'1' 表示目录
f_Record.favCat:='title1'; //'title4' 是 'title1's 的子节点,且这个节点也是一个目录
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title5';
f_Record.favIsCat:=''; //'' 表示节点
f_Record.favCat:='title4'; //'title5' 是 'title4's 的子节点。
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title6';
f_Record.favIsCat:=''; // '' 表示节点
f_Record.favCat:='title1'; //'title6' 是 'title1's 的子节点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title7';
f_Record.favIsCat:=''; //'' 表示节点
f_Record.favCat:='title4'; //'title7' 是 'title4's 的子节点
rsList.Add(f_Record);

s:= createJsonString(rsList);
end;


...全文
148 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
wdonghai 2009-10-21
  • 打赏
  • 举报
回复
解决这个问题,需要分两步。
第一步要解决从List构造正确的结点树。(要确保结点资料正确,父子关系要正确。)
第二步根据结点树生成字符串。

...
Button1: TButton;
Memo1: TMemo;
TV1: TTreeView;
...

type
PFavoritRecord=^TFavoritRecord;
TFavoritRecord=record
favTitle:string;
favIsCat:string;
favCat:string;
end;

function FXTree(tv:TTreeView):string;
const
cCRLR=#13#10;
var
s:string;

function GSS(ASpaceLen:Integer):string;//Gen Space String:生成空格函数
var
i:integer;
begin
SetLength(result,ASpaceLen);
for i:=1 to ASpaceLen do
result[i]:=' ';
end;

procedure DFS(ANode:TTreeNode;Level:Integer);
var
i,iLevel,iLeft:Integer;
begin
if (ANode<>nil) then
begin
iLevel:=ANode.Level;
iLeft:=8*(iLevel+1);
s:=s+GSS(iLeft)+'{'+cCRLR+
GSS(iLeft+4)+'''id'':'''+inttostr(ANode.AbsoluteIndex+1)+''','+cCRLR+
GSS(iLeft+4)+'''txt'':'''+PFavoritRecord(ANode.Data)^.favTitle+'''';

if (ANode.HasChildren) then
begin
s:=s+','+cCRLR+GSS(iLeft+4)+
'''items'':['+cCRLR;
end
else begin
s:=s+cCRLR+GSS(iLeft)+'}';
if ANode.getNextSibling<>nil then //同级上没有后续结点
s:=s+',';
s:=s+cCRLR;
end;

if ANode.GetNext<>nil then //处理后一个结点与当前结点是否在同一级上
begin
Level:=ANode.GetNext.Level;
Level:=iLevel-Level;
for i:=0 to Level-1 do //处理后续结点与当前结点相差的级别
begin
iLeft:=8*(iLevel-i);
s:=s+GSS(iLeft+4)+']'+cCRLR+
GSS(iLeft)+'}';
if i=Level-1 then s:=s+',';
s:=s+cCRLR;
end;
end;

DFS(ANode.GetNext,iLevel);
end;
end;

begin
if tv.Items.Count=0 then exit;

s:='['+cCRLR;

DFS(tv.Items[0],0);

result:=s+']';
end;

function createJsonString(rs:TList;tv:TTreeView):String;
var
sList:TList;
i,j:integer;
p:PFavoritRecord;
node,pnode:TTreeNode;
sTitle:string;
begin
sList:=TList.Create;
try
//把目录提取出来
for i:=rs.Count-1 downto 0 do
begin
p:=rs.Items[i];

if p.favIsCat<>'' then //目录
begin
sList.Add(p);
rs.Delete(i);
end;
end;

//处理目录
i:=0;
while sList.Count>0 do
begin
p:=sList.Items[i];

//处理根目录
if p^.favCat='' then
begin
tv.Items.AddObject(nil,p^.favTitle,p);
sList.Delete(i);
if i>0 then dec(i);
end
else if p^.favCat<>'' then
begin //一般目录
//检查在目录树上是否已经查到该目录的父目录
sTitle:=p^.favCat;
node:=nil;
for j:=0 to tv.Items.Count-1 do
if sTitle=PFavoritRecord(tv.Items[j].Data)^.favTitle then
begin
node:=tv.Items[j];
break;
end;

if node<>nil then
begin
tv.Items.AddChildObject(node,p^.favTitle,p);
sList.Delete(i);
if i>0 then dec(i);
end
else inc(i);
end;
end;

//处理剩下的结点
for i:=0 to rs.Count-1 do
begin
p:=rs.Items[i];

sTitle:=p^.favCat;
node:=nil;
for j:=0 to tv.Items.Count-1 do
if sTitle=PFavoritRecord(tv.Items[j].Data)^.favTitle then
begin
node:=tv.Items[j];
break;
end;

if node<>nil then
begin
//查到该结点下的所有子结点中出现子结点是目录的第一个子结点,
//主要是为了控制将结点插在目录结点的上面
pnode:=node.getFirstChild;
while pnode<>nil do
begin
if PFavoritRecord(pnode.Data)^.favIsCat<>'' then break;
pnode:=pnode.getNextSibling;
end;

if (pnode<>nil) and (PFavoritRecord(pnode.Data)^.favIsCat<>'') then
tv.Items.InsertObject(pnode,p^.favTitle,p)
else
tv.Items.AddChildObject(node,p^.favTitle,p);
end
else tv.Items.AddChildObject(nil,p^.favTitle,p);//顶级结点
end;

result:=FXTree(tv);
finally
sList.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
f_Record: PFavoritRecord;
rsList:TList;
begin
rsList:=TList.Create;

new(f_Record);
f_Record.favTitle:='title1';
f_Record.favIsCat:='1'; //1: 表示是目录
f_Record.favCat:=''; //‘’表示是根目录
rsList.add(f_Record);

new(f_Record);
f_Record.favTitle:='title2';
f_Record.favIsCat:=''; //'' 表示是节点
f_Record.favCat:=''; //'' 表示是根结点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title3';
f_Record.favIsCat:=''; //'' 节点
f_Record.favCat:=''; //'' 根结点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title4';
f_Record.favIsCat:='1'; //'1' 表示目录
f_Record.favCat:='title1'; //'title4' 是 'title1's 的子节点,且这个节点也是一个目录
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title5';
f_Record.favIsCat:=''; //'' 表示节点
f_Record.favCat:='title4'; //'title5' 是 'title4's 的子节点。
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title6';
f_Record.favIsCat:=''; // '' 表示节点
f_Record.favCat:='title1'; //'title6' 是 'title1's 的子节点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title7';
f_Record.favIsCat:=''; //'' 表示节点
f_Record.favCat:='title4'; //'title7' 是 'title4's 的子节点
rsList.Add(f_Record);

{new(f_Record);
f_Record.favTitle:='title8';
f_Record.favIsCat:='1'; //'' 表示目录
f_Record.favCat:='title1'; //'title8' 是 'title1's 的子节点
rsList.Add(f_Record);

new(f_Record);
f_Record.favTitle:='title9';
f_Record.favIsCat:=''; //'' 表示节点
f_Record.favCat:='title8'; //'title9' 是 'title8's 的子节点
rsList.Add(f_Record);}

TV1.Items.Clear;
Memo1.Text:= createJsonString(rsList,TV1);
rsList.Free;
end;
iseekcode 2009-10-17
  • 打赏
  • 举报
回复
知道规则后,应该可以吧.凡子节点就加#9.
使用一个变量,用以比对当前节点.
haitao 2009-10-17
  • 打赏
  • 举报
回复
treeview.savetofile得到的就是一个树形的字符串文本
再在适当的地方加上{、}即可
windindance 2009-10-17
  • 打赏
  • 举报
回复
要看你本身 TList的结构。
写代码太麻烦了
注意 Json输出的字符串实际上就是javascript中的对象数组。
你可以先从最简单的写起,先输出最基本的数组,然后数组中嵌套对象,对象中再嵌套数组而已。

16,749

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧