如何将文本文件大纲列表转换为对象的递归集合?
如何将此文本文件内容转换为可以绑定到TreeView的对象递归集合?即我想最终得到 3 个对象 的集合,第一个名为 countries 的集合,它包含三个子对象的集合:france, 德国、意大利等等...
答案:感谢所有为此提供帮助的人,这是我成功解析此文本的代码大纲到 XAML 树中: http://tanguay.info/web/ index.php?pg=codeExamples&id=358
countries
-france
--paris
--bordeaux
-germany
-italy
subjects
-math
--algebra
--calculus
-science
--chemistry
--biology
other
-this
-that
下面的代码是我所得到的,但它没有正确处理父母的多个孩子。
using System;
using System.Collections.Generic;
using System.Text;
namespace TestRecursive2342
{
class Program
{
static void Main(string[] args)
{
List<OutlineObject> outlineObjects = new List<OutlineObject>();
//convert file contents to object collection
List<string> lines = Helpers.GetFileAsLines();
Stack<OutlineObject> stack = new Stack<OutlineObject>();
foreach (var line in lines)
{
OutlineObject oo = new OutlineObject(line);
if (stack.Count > 0)
{
OutlineObject topObject = stack.Peek();
if (topObject.Indent < oo.Indent)
{
topObject.OutlineObjects.Add(oo);
stack.Push(oo);
}
else
{
stack.Pop();
stack.Push(oo);
}
}
else
{
stack.Push(oo);
}
if(oo.Indent == 0)
outlineObjects.Add(oo);
}
outlineObjects.ForEach(oo => Console.WriteLine(oo.Line));
Console.ReadLine();
}
}
public class OutlineObject
{
public List<OutlineObject> OutlineObjects { get; set; }
public string Line { get; set; }
public int Indent { get; set; }
public OutlineObject(string rawLine)
{
OutlineObjects = new List<OutlineObject>();
Indent = rawLine.CountPrecedingDashes();
Line = rawLine.Trim(new char[] { '-', ' ', '\t' });
}
}
public static class Helpers
{
public static List<string> GetFileAsLines()
{
return new List<string> {
"countries",
"-france",
"--paris",
"--bordeaux",
"-germany",
"-italy",
"subjects",
"-math",
"--algebra",
"--calculus",
"-science",
"--chemistry",
"--biology",
"other",
"-this",
"-that"};
}
public static int CountPrecedingDashes(this string line)
{
int tabs = 0;
StringBuilder sb = new StringBuilder();
foreach (var c in line)
{
if (c == '-')
tabs++;
else
break;
}
return tabs;
}
}
}
How can I convert this text file content into a recursive collection of objects that I can bind to a TreeView? i.e. I want to end up with a collection of 3 objects, the first one called countries which has a collection of three child objects: france, germany, italy, and so on...
ANSWER: thanks to all who helped out on this, here's my code that successfully parses this text outline into a XAML tree: http://tanguay.info/web/index.php?pg=codeExamples&id=358
countries
-france
--paris
--bordeaux
-germany
-italy
subjects
-math
--algebra
--calculus
-science
--chemistry
--biology
other
-this
-that
The code below is as far as I got it, but it is not dealing with multiple children of parents correctly.
using System;
using System.Collections.Generic;
using System.Text;
namespace TestRecursive2342
{
class Program
{
static void Main(string[] args)
{
List<OutlineObject> outlineObjects = new List<OutlineObject>();
//convert file contents to object collection
List<string> lines = Helpers.GetFileAsLines();
Stack<OutlineObject> stack = new Stack<OutlineObject>();
foreach (var line in lines)
{
OutlineObject oo = new OutlineObject(line);
if (stack.Count > 0)
{
OutlineObject topObject = stack.Peek();
if (topObject.Indent < oo.Indent)
{
topObject.OutlineObjects.Add(oo);
stack.Push(oo);
}
else
{
stack.Pop();
stack.Push(oo);
}
}
else
{
stack.Push(oo);
}
if(oo.Indent == 0)
outlineObjects.Add(oo);
}
outlineObjects.ForEach(oo => Console.WriteLine(oo.Line));
Console.ReadLine();
}
}
public class OutlineObject
{
public List<OutlineObject> OutlineObjects { get; set; }
public string Line { get; set; }
public int Indent { get; set; }
public OutlineObject(string rawLine)
{
OutlineObjects = new List<OutlineObject>();
Indent = rawLine.CountPrecedingDashes();
Line = rawLine.Trim(new char[] { '-', ' ', '\t' });
}
}
public static class Helpers
{
public static List<string> GetFileAsLines()
{
return new List<string> {
"countries",
"-france",
"--paris",
"--bordeaux",
"-germany",
"-italy",
"subjects",
"-math",
"--algebra",
"--calculus",
"-science",
"--chemistry",
"--biology",
"other",
"-this",
"-that"};
}
public static int CountPrecedingDashes(this string line)
{
int tabs = 0;
StringBuilder sb = new StringBuilder();
foreach (var c in line)
{
if (c == '-')
tabs++;
else
break;
}
return tabs;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这应该可以解决问题。我在你的文本文件上测试了它。可能存在一些错误。测试一下并判断它是否有效。
编辑:实际上,经过进一步测试后发现这并不能按预期工作。您需要添加更多逻辑才能使其正常工作。我把这个留给你。
编辑:在对代码进行更多测试后,我得到了一个效果更好的版本。我仍然不能保证它在所有情况下都有效。
This should do the trick. I tested it on your text file. There might be some bugs. Test it and tell if it works.
EDIT: Actually after further testing it turns out this does not work as expected. You need to add more logic to make it work. I leave that to you.
EDIT: After testing the code a bit more I have come to a version that works better. I still cannot guarantee that It will work under all circumstances.
您应该使您的
OutlineObject
包含子OutlineObject
列表。这样您就可以绑定到树视图中的子集合。请查看此处示例。或者此处。
为了进行解析,您应该维护嵌套对象的
Stack
。当您读取下一个
OutlineObject
时,请查看堆栈中最后一个OutlineObject
的深度。如果您的级别更高,您可以将自己添加为该OutlineObject
的子级,并将您的OutlineObject
压入堆栈。如果您的级别相同,则删除该OutlineObject
并推送您的对象。如果您的级别更大,请删除顶部堆栈OutlineObject
,然后重复检查。关于您要添加的更改
...此代码不检查新对象的级别小于堆栈顶部的级别的情况。你需要:
You should make your
OutlineObject
contain a list of childOutlineObject
s. This way you can bind to the child collection in tree views.Look here for an example. Or here.
For parsing, you should maintain a
Stack<OutlineObject>
of your nested objects.When you read next
OutlineObject
, look at the depth of the lastOutlineObject
in the stack. If your level is greater, you add yourself as a child of thatOutlineObject
, and push yourOutlineObject
onto the stack. If your level is the same, you remove thatOutlineObject
and push your object instead. If your level is bigger, you remove that top stackOutlineObject
, and repeat the check.Regarding your change to add
...this code doesn't check for the case when the level of new object is smaller than the level of stack top. You'll need:
简单的。
创建一个 OutlineObject 对象列表,每个级别一个,这些对象将作为父级。
因此,算法:
这应该会给你你的树结构。您需要在每个对象中保留一个子列表。
另请注意,如果您希望上面的列表处理文件中的错误,则需要进行额外的错误检查,如下所示:
在这种情况下,最后一个子级将添加为“child 1”的子级,而不是“另一个根”的子级”。
Simple.
Create a list of OutlineObject objects, one for each level, these will serve as the parents.
So, the algorithm:
This should give you your tree structure. You will need to keep a child-list in each object.
Also note that the above list will need additional error checking if you want it to handle errors in the file, like this:
In this case, the last child there will be added as a child of "child 1", not of "another root".
复合模式是我首先想到的......
The Composite pattern is the first thing that comes to mind for me...
这是我的尝试,它是你最初的努力加上 Diamandiev 的方法的结合。我还添加了一个递归 Output() 方法,它将有效地重现原始输入文件。
不幸的是,我无法完全理解堆栈方法,但有兴趣查看一个有效的示例。
请注意,这仅允许您给定的节点嵌套 3 层的示例。如果超过这个值,则需要修改
else if ((oo.Indent - lastItem.Indent) < 0)
检查。Here's my attempt which is a combination of your original effort plus diamandiev's approach. I also added a recursive Output() method which will effectively reproduce the original input file.
Unfortunately I couldn't quite fathom the stack approach, but would be interested to see a working example.
Note that this only allows for your given example of nodes being nested 3 levels deep. Any more than that will require a modification to the
else if ((oo.Indent - lastItem.Indent) < 0)
check.多么好的解决方案啊!这可以成为一个方便的小实用程序。太完美了。
我知道你发布这篇文章已经有一段时间了;我无法找到原件,但我找到了存档的副本 此处。
为了简洁起见,我对其进行了一些修改,并将其翻译为 VB.NET,供那些可能感兴趣的人使用。
最终结果如下:
主
测试
树
节点
扩展
What a great solution! This could make for a handy little utility. It's perfect.
I know it's been a while since you posted this; I wasn't able to locate the original but I found a copy archived here.
I've modified it a bit for brevity and translated it to VB.NET for those who may be interested.
Here's the end result:
Main
Test
Tree
Node
Extensions