如何在层级列表中查找并删除指定对象

.Net技术 码拜 6年前 (2015-03-18) 306次浏览 0个评论

各位大神,
遇到这样一个问题,我有这样一个对象,
pre class=”brush: csharp”>    public class Question
    {
        public List<Question> Questions { get; set; }
        public string Title { get; set; }
        public int Score { get; set; }
    }
在Question对象中会嵌套一个List<Question>对象。
这是我模拟的一个Question列表,
pre class=”brush: html”> List<Question> QuestionList = new List<Question>();
            Question Q11 = new Question()
            {
                Title = “1.1”,
                Score = 5,
            };
            Question Q12 = new Question()
            {
                Title = “1.2”,
                Score = 5,
            };
            Question Q13 = new Question()
            {
                Title = “1.3”,
                Score = 5,
            };
            List<Question> Q13List = new List<Question>();
            Question Q131 = new Question()
            {
                Title = “1.3.1”,
                Score = 5,
            };
            Question Q132 = new Question()
            {
                Title = “1.3.2”,
                Score = 5,
            };
            List<Question> Q132List = new List<Question>();
            Question Q1321 = new Question()
            {
                Title = “1.3.2.1”,
                Score = 5,
            };
            Question Q1322 = new Question()
            {
                Title = “1.3.2.2”,
                Score = 5,
            };
            Question Q1323 = new Question()
            {
                Title = “1.3.2.3”,
                Score = 5,
            };
            Q132.Questions = Q132List;
            Q13List.Add(Q131);
            Q13List.Add(Q132);
            Q13.Questions = Q13List;
            List<Question> Q1List = new List<Question>();
            Q1List.Add(Q11);
            Q1List.Add(Q12);
            Q1List.Add(Q13);
            Question Q1 = new Question()
            {
                Title = “First One”,
                Score = 25,
                Questions = Q1List,
            };
            Question Q2 = new Question()
            {
                Title = “Second”,
                Score = 25,
            };
            Question Q3 = new Question()
            {
                Title = “Third”,
                Score = 25,
            };
            QuestionList.Add(Q1);
            QuestionList.Add(Q2);
            QuestionList.Add(Q3);
然后我需要找到这个列表中一个指定的Question对象,并从中删除它,这个Question可能是第一层的,也可能是第二层的,例如我要找到并删除,
pre class=”brush: csharp”>            Question needDeleteQuestion = new Question()
            {
                Title = “1.3.2”,
                Score = 5,
            };
我该怎么做呢?如何找到这个需要删除的Question。

 
如何在层级列表中查找并删除指定对象
20分
给你写了一个demo

using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Question> QuestionList = new List<Question>();
            Question Q11 = new Question()
            {
                Title = "1.1",
                Score = 5,
            };
            Question Q12 = new Question()
            {
                Title = "1.2",
                Score = 5,
            };
            Question Q13 = new Question()
            {
                Title = "1.3",
                Score = 5,
            };
            List<Question> Q13List = new List<Question>();
            Question Q131 = new Question()
            {
                Title = "1.3.1",
                Score = 5,
            };
            Question Q132 = new Question()
            {
                Title = "1.3.2",
                Score = 5,
            };
            List<Question> Q132List = new List<Question>();
            Question Q1321 = new Question()
            {
                Title = "1.3.2.1",
                Score = 5,
            };
            Question Q1322 = new Question()
            {
                Title = "1.3.2.2",
                Score = 5,
            };
            Question Q1323 = new Question()
            {
                Title = "1.3.2.3",
                Score = 5,
            };
            Q132.Questions = Q132List;
            Q13List.Add(Q131);
            Q13List.Add(Q132);
            Q13.Questions = Q13List;
            List<Question> Q1List = new List<Question>();
            Q1List.Add(Q11);
            Q1List.Add(Q12);
            Q1List.Add(Q13);
            Question Q1 = new Question()
            {
                Title = "First One",
                Score = 25,
                Questions = Q1List,
            };
            Question Q2 = new Question()
            {
                Title = "Second",
                Score = 25,
            };
            Question Q3 = new Question()
            {
                Title = "Third",
                Score = 25,
            };
            QuestionList.Add(Q1);
            QuestionList.Add(Q2);
            QuestionList.Add(Q3);
            var all = GetAll(QuestionList);
            Console.WriteLine("现在总共有 {0} 个Question。", all.Count());
            var search = (from t in all
                          let q = t.Item1
                          where q.Title == "1.3.2" && q.Score == 5
                          select t).ToList();
            Console.WriteLine("找到{0}个符合条件的Question。", search.Count);
            if (search.Any(r => r.Item1.Questions != null && r.Item1.Questions.Count > 0))
                throw new Exception("Question的Questions集合不是空的,不能删除。");
            foreach (var r in search)
                r.Item2.Questions.Remove(r.Item1);      //从父Question的Questions属性中删除子Quenstion
            Console.WriteLine("总共有 {0} 个Question。", GetAll(QuestionList).Count());
            Console.WriteLine("_________________按任意键结束。");
            Console.ReadKey();
        }
        /// <summary>
        /// 返回所有的Question极其父Question。
        /// </summary>
        /// <param name="list">要遍历的树。</param>
        /// <returns>返回子Question及其父Question的 Tuple 结构列表。
        /// 对于顶级Question,则父Question为null。</returns>
        public static IEnumerable<Tuple<Question, Question>> GetAll(List<Question> list)
        {
            foreach (var r in GetAll(list, null))
                yield return r;
        }
        private static IEnumerable<Tuple<Question, Question>> GetAll(List<Question> list, Question parent)
        {
            foreach (var q in list)
            {
                yield return new Tuple<Question, Question>(q, parent);
                var children = q.Questions;
                if (children != null && children.Count > 0)
                    foreach (var r in GetAll(q.Questions, q))
                        yield return r;
            }
        }
    }
    public class Question
    {
        public List<Question> Questions { get; set; }
        public string Title { get; set; }
        public int Score { get; set; }
    }
}
/pre>
要删除它,必须先找到它。而要找到它,就需要递归搜索。
在数据结构上,由于需要知道它的parent才能删除它,因此搜索的结果是得到 Tuple<Question,Question> 这样的“子-父”结构。
在搜索功能上,使用了c#的迭代器功能,方便于将搜索应用到各种灵活的枚举功能的场合。例如使用 Linq 中。
如何在层级列表中查找并删除指定对象
10分
这里边有两个功能点:
首先是 GetAll 方法中,使用 5、6行代码对树进行深度优先搜索,并且以c#的迭代器模式输出出来。
第二点就是在数据结构上返回了“子Question与其父Question的元组”。当然你也可以自定义一个有着两个属性的class。关键是要知道返回“两个”属性才够进行后续删除动作。
如何在层级列表中查找并删除指定对象
10分
实际开发中,需要反之无限递归的情况出现。(你可以设计一个测试用例,仅仅有2个Questiion,就能产生一个无限递归)
这个你自己修改吧。有多种形式。例如可以在递归查找(第二个Get方法)的参数上增加一个“已经查找出来的Question的收集集合,在 yield return 返回结果之前先判断一下是否重复。或者(更轻量的方式)是在这个方法参数上仅增加一个“递归深度”数值,并且程序判断最多仅递归5层。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明如何在层级列表中查找并删除指定对象
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!