【问题标题】:How to sum the value of child items from a hierarchical list in a loop如何在循环中对分层列表中的子项的值求和
【发布时间】:2018-05-20 09:25:36
【问题描述】:

如何在循环中对分层列表中的子项的值求和。

我需要在列表中的循环过程中,amount 和 price 属性的值包含子项的这些属性的总和。

以下是用于帮助我解决问题的两个类。

namespace SGP.Dto.Custo
{    
    public class PlanilhaCusto
    {   
        public int id{ get; set; }
        public int parenteId{ get; set; }      
        public string name { get; set; }
        public decimal amount{ get; set; }
        public decimal price{ get; set; }

        public PlanilhaCusto(int pId, int pParenteId, pName, decimal pAmount, decimal pPrice)
        {
            id = pId;
            parentId = pParentId;
            name = pName;
            amount = pAmount;
            price = pPrice;
        }        
    }    
}

namespace SGP.Dto.Custo
{
    public class ShowList
    {
        List<Dto.Custo.PlanilhaCusto> myList = new List<PlanilhaCusto>();

        public void Show()
        {    
            myList.Add(new PlanilhaCusto(1, null, "Projetos", 0, 0));
            myList.Add(new PlanilhaCusto(2, 1, "Arquitetura", 5,10));
            myList.Add(new PlanilhaCusto(3, 1, "Estrutura", 0, 0));
            myList.Add(new PlanilhaCusto(4, 3, "Civil", 1, 50));
            myList.Add(new PlanilhaCusto(5, 3, "Infra", 3, 75));
            myList.Add(new PlanilhaCusto(6, null, "Pessoal", 0, 0));
            myList.Add(new PlanilhaCusto(7, 6, "Mão de Obra", 20, 5700));

            /*In this loop the value of the parent items must be updated 
              (calculated). The hierarchy of the list can be unlimited, 
              like a tree. I tried using a recursive method but I could 
              not do it.*/
            foreach (var itemList in myList)
            {

            }  
        }
    }
}

【问题讨论】:

  • “我尝试使用递归方法,但我做不到”请发布您尝试过的什么。在最坏的情况下,这里有人会编写完全相同的解决方案,因为我们不知道您已经尝试过什么。但是我怀疑这会对您有所帮助,不是吗?
  • 你有没有尝试过?
  • 这是来自测试或诅咒之类的问题吗?

标签: c# list linq recursion hierarchical


【解决方案1】:

假设列表中的元素按照您的示例中的方式排序,最快的方法应该是以相反的顺序遍历列表并将数量添加到具有正确 ID 的列表条目中。

  1. 向后遍历列表
  2. 当当前元素有父元素时,向其添加金额和金额*价格

编辑:

在阅读了您在来源中的评论后,我假设您已经知道我刚刚写了什么。

我的方法如下:

        for (int i = myList.Count - 1; i > 1; i--)
        {
            var temp = myList.ElementAt(i);
            if (temp.parentId != null)
            {
                var parent = myList.ElementAt(temp.parentId - 1);
                parent.amount += temp.amount;
                parent.price += (temp.amount * temp.price);
            }
        }

【讨论】:

    【解决方案2】:

    为了创建层次结构,我将您的 PlanilhaCusto 修改为类似于树中的一种节点,同时具有父成员和子成员,以便于遍历

    public class PlanilhaCusto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int? ParentId { get; set; }
        public decimal Amount { get; set; }
        public decimal Price { get; set; }
        public IEnumerable<PlanilhaCusto> Children { get; set; }
    }
    

    给定这个结构和初始输入

    你可以构建整个树结构,无论有多少层都依赖于一些递归

    public IEnumerable<PlanilhaCusto> Descendants(PlanilhaCusto parent, IEnumerable<PlanilhaCusto> source)
    {
        var query = from node in source
                    where node.ParentId == parent.Id
                    let children = Descendants(node, source)
                    select new PlanilhaCusto
                    {
                        Id = node.Id,
                        ParentId = node.ParentId,
                        Name = node.Name,
                        Amount = node.Amount,
                        Price = node.Price,
                        Children = children,
                    };
    
        return query.ToList();
    }
    
    var hierarchy = from node in source
                    let children = Descendants(node, source)
                    where node.ParentId == null
                    select new PlanilhaCusto
                    {
                        Id = node.Id,
                        ParentId = node.ParentId,
                        Name = node.Name,
                        Price = node.Price,
                        Children = children,
                    };
    

    这会将初始数据源投射到类似的东西中

    从这里你只需要遍历层次结构并组成总价格

    public decimal? Total(PlanilhaCusto node)
    {
        decimal? price = node.Price * node.Amount;
        if (node.Children != null)
        {
            foreach (var child in node.Children)
            {
                price += Total(child);
            }
        }
    
        return price;
    }
    
    var totals = from node in hierarchy
                 select new 
                 {
                    Id = node.Id,
                    Name = node.Name,
                    Total = Total(node),
                 };
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 2015-01-11
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多