C#递归编程与列表

时间:2012-09-03 03:06:36

标签: c# class recursive-datastructures

我正在开发一个程序,每个项目都可以容纳一个项目数组(我正在制作一个菜单,它有一个树状结构)

目前我将这些项目作为列表而不是数组,但我不觉得我正在使用它来充分发挥简化代码的潜力。我在标准数组上选择了一个列表,因为接口(.add,.remove等等)很有意义。

我有代码搜索结构并返回名称的路径(即Item.subitem.subsubitem.subsubsubitem)。以下是我的代码:

public class Item
{
                                                                //public Item[] subitem; <-- Array of Items
    public List<Item> subitem;                                  // <-- List of Items

    public Color itemColor = Color.FromArgb(50,50,200);
    public Rectangle itemSize = new Rectangle(0,0,64,64);
    public Bitmap itemBitmap = null;
    public string itemName;


    public string LocateItem(string searchName)
    {
        string tItemName = null;

        //if the item name matches the search parameter, send it up)
        if (itemName == searchName)
        {
            return itemName;
        }

        if (subitem != null)
        {

            //spiral down a level
            foreach (Item tSearchItem in subitem)
            {
                tItemName = tSearchItem.LocateItem(searchName);

                if (tItemName != null)
                    break;  //exit for if item was found
            }
        }


        //do name logic (use index numbers)
        //if LocateItem of the subitems returned nothing and the current item is not a match, return null (not found)
        if (tItemName == null && itemName != searchName)
        {
            return null;
        }

        //if it's not the item being searched for and the search item was found, change the string and return it up
        if (tItemName != null && itemName != searchName)
        {
            tItemName.Insert(0, itemName + ".");  //insert the parent name on the left -->  TopItem.SubItem.SubSubItem.SubSubSubItem
            return tItemName;
        }

        //default not found
        return null;
    }


}

我的问题是,是否有更简单的方法来执行此操作?我一直在脑子里来回询问我是应该使用列表还是仅使用数组。我有一个列表的唯一原因是,每次添加或删除项目时,我都不必编写代码来调整数组大小。

3 个答案:

答案 0 :(得分:2)

在这种情况下使用列表是完全可以接受的。如果性能是一个问题,阵列将是一个更好的选择 - 如果是这样,阵列会稍微快一点,但你发现的灵活性要差得多。

人们没有充分讨论的一件事是,简单性是构建代码的重要基础。如果使用列表而不是数组编写和维护更简单,那么(所有其他条件相同)使用列表是完全正确的。

答案 1 :(得分:2)

列表听起来很棒。我建议你定义一个变体。尝试创建这样的类:

public class Item : List<Item>
{
    public string Name;
}

如果您从Item继承List<Item>,则会自动将其设为树而不需要subitem字段。

这是我班级的完整版本:

public class Item : List<Item>
{
    public string Name;

    private List<Item> LocateItems(string searchName)
    {
        if (this.Name == searchName)
            return (new [] { this }).ToList();

        var result =
            this
                .Select(s => s.LocateItems(searchName))
                .Where(x => x !=null && x.Count > 0)
                .FirstOrDefault();

        if (result != null)
            result.Add(this);

        return result;
    }

    public string LocateItem(string searchName)
    {
        var items = this.LocateItems(searchName);
        if (items == null)
            return null;
        else
            return String.Join(".", items.Select(i => i.Name).Reverse());
    }
}

方法LocateItems会返回Item列表,其中Item以匹配并跟随所有父Item个实例的var foos = new Item() { Name = "Foo" }; var bars = new Item() { Name = "Bar" }; var qazs = new Item() { Name = "Qaz" }; var wees = new Item() { Name = "Wee" }; foos.Add(bars); bars.Add(qazs); foos.Add(wees); Console.WriteLine(foos.LocateItem("Wee")); Console.WriteLine(foos.LocateItem("Qaz")); Console.WriteLine(foos.LocateItem("Bar")); Console.WriteLine(foos.LocateItem("Foo")); 开头,直到并包含根。< / p>

我测试了这段代码:

Foo.Wee
Foo.Bar.Qaz
Foo.Bar
Foo

我得到了这些结果:

{{1}}

答案 2 :(得分:1)

我会建议列表。由于向数组添加/删除项目会重新分配内存,因此对于项目的动态集合(我假设是您的情况),列表通常具有更好的整体性能。您可能需要查看:

Array versus List<T>: When to use which?