【问题标题】:Add nested values from nested class lists in Linq从 Linq 中的嵌套类列表中添加嵌套值
【发布时间】:2017-03-16 06:38:01
【问题描述】:

我很抱歉代码量很大,但是很难真正解释每个类的结构,所以我希望我包含这么多是可以的。所以我在 C# 中使用 Linq 学习更复杂的查询。其中大多数涉及从大量嵌套对象中查询大量字段。

我的问题是弄清楚如何获取我想要的信息。例如,我现在坚持的那个促使我这样做的原因如下所示。我要查询所有已下订单的订单 ID、客户名字/姓氏和总数。还有许多其他生成的对象,但它们没有放置状态,所以我没有包括它们。

如下所示的当前查询,返回 4 次 Roger 和 5 次 Mary。这是正确的,因为它是编码的,因为它们是 Roger 的 4 个加法和 Mary 的 5 个加法。但是,我没有得到姓氏,并且对于如何汇总所有订单一无所知。

当尝试使用任何类型的 .Sum 或 .Count 功能时,它无法识别。我知道我可能无法使用我选择的新语句正确地塑造数据。我正在寻找一些关于如何最小化输出数据量以及完成总计的方向的见解。

 class Customer
        {
            public int CustomerID { get; set; }
            public String FirstName { get; set; }
            public String LastName { get; set; }
            public String Email { get; set; }

            public Customer(int id, String fName, String lName, String email)
            {
                CustomerID = id;
                FirstName = fName;
                LastName = lName;
                Email = email;
            }
        }
    }

        class Order
    {
        public int OrderID { get; set; }
        public DateTime OrderDate { get; set; }
        public String ShippingMethod { get; set; }
        public String OrderStatus { get; set; }
        public Customer OrderedBy { get; set; }
        public List<Product> OrderItems { get; set; }

        public Order(int ordId, DateTime ordDate, String shipMethod, String ordStatus, Customer cust)
        {
            OrderID = ordId;
            OrderDate = ordDate;
            ShippingMethod = shipMethod;
            OrderStatus = ordStatus;
            OrderedBy = cust;
            OrderItems = new List<Product>();
        }

        public void addProduct(Product prod)
        {
            OrderItems.Add(prod);
        }
        public double calcOrderTotal()
        {

            var itemVar = OrderItems.Sum(i => i.calcProductTotal());

            return itemVar;
        }
        public double calcShipping()
        {
            double total = 0;
            return total;
        }

    }
}

    class Product
    {
        public int ProdID { get; set; }
        public String Name { get; set; }
        public double Price { get; set; }
        public String Image { get; set; }
        public String Desc { get; set; }
        public int QtyOrdered { get; set; }
        public double Weight { get; set; }

        public Product(int id, string name, double price)
        {
            ProdID = id;
            Name = name;
            Price = price;
        }
        public Product(int id, string name, double price, string image, string desc)
            : this(id, name, price)
        {
            Image = image;
            Desc = desc;
        }
        public Product(int id, string name, double price, int qty, double weight) : this(id, name, price)
        {
            QtyOrdered = qty;
            Weight = weight;
        }
        public double calcProductTotal()
        {
            return Price * QtyOrdered;
        }
    }
}

   class Program
{
    static void Main(string[] args)
    {   //http://msdn.microsoft.com/en-us/vcsharp/aa336746
        List<Order> orders2 = setupData2();

private static List<Order> setupData2()
        {
    List<Order> orders = new List<Order>();
            Customer c1 = new Customer(14, "Mary", "Smith", "msmith@gmail.com");
            Customer c2 = new Customer(25, "Andy", "Johnson", "andy.johnson@gmail.com");
            Customer c3 = new Customer(42, "Tim", "Clark", "tc@tc.net");
            Customer c4 = new Customer(125, "Roger", "Wilson", "rogerw@zmail.com");

    Order ord4 = new Order(48, DateTime.Now.Subtract(new TimeSpan(4, 1, 1, 1, 1)), "Ground", "Placed", c4);
            ord4.addProduct(new Product(129, "Do It Yourself Tornado Kit", 225.50, 4, 85.5));
            ord4.addProduct(new Product(421, "Catcus Costume", 48.70, 2, 18.85));
            ord4.addProduct(new Product(400, "Anvil", 338.70, 1, 384.25));
            ord4.addProduct(new Product(455, "Jet Propelled Unicycle", 556.40, 4, 328.35));
            orders.Add(ord4);

            Order ord5 = new Order(55, DateTime.Now.Subtract(new TimeSpan(1, 1, 1, 1, 1)), "Ground", "Placed", c1);
            ord5.addProduct(new Product(124, "Earth Quake Pills", 145.50, 3, 2.25));
            ord5.addProduct(new Product(129, "Do It Yourself Tornado Kit", 225.50, 1, 85.5));
            ord5.addProduct(new Product(327, "Giant Mouse Trap", 88.70, 4, 26.50));
            ord5.addProduct(new Product(400, "Anvil", 338.70, 2, 384.25));
            ord5.addProduct(new Product(425, "Iron Bird Seed", 27.70, 1, 5.85));
            orders.Add(ord5); }

                                var orders = (from o in orders2
                      from p in o.OrderItems
                      where o.OrderStatus == "Placed"
                      orderby o.OrderDate
                      let total = p.Price * p.QtyOrdered
                      select new { o.OrderID, o.OrderedBy.FirstName, o.OrderedBy.LastName, Total = total });
        double totalOrders = 0;
        foreach (var x in orders)
        {            
            Console.WriteLine("Order Id: " + x.OrderID + " Ordered by: " + x.FirstName + " " + x.LastName);
            totalOrders+= x.Total;
        }
        Console.WriteLine("Price for all Orders: " + totalOrders);
}

可能的 groupby 解决方案,但现在无法提取名称。

            var ordersTotal = from o in orders2
                          from p in o.OrderItems
                          where o.OrderStatus == "Placed"
                          orderby o.OrderDate
                          group p by o.OrderID into g
                          select new { OrderId = g.Key, Price = g.Sum(p => p.Price * p.QtyOrdered) };

【问题讨论】:

  • 你从哪里得到订单2?
  • 首先你有两个名为 orders 的对象(错误的编码),其次你没有得到 LastName 因为你的匿名类型有 o.OrderedBy.LastName 当你将项目放入这种类型时,它已经被任何命令排序了之前orderby o.OrderDate
  • @nick-s 抱歉,这是我对订单集合的初始化。现在应该正确更新代码。它只是在其中创建包含所有订单的列表,这是 SetupData2 方法,我将其称为 List orders2。
  • 我找不到 setupData2() 方法!?
  • @nick-s 现在检查,格式应该是正确的。

标签: c# linq


【解决方案1】:

试试这个代码。

            var orders = (from o in orders2
                          where o.OrderStatus == "Placed"
                          orderby o.OrderDate
                          select new { o.OrderedBy.FirstName, o.OrderedBy.LastName }).Distinct();

            foreach (var x in orders)
            {
                Console.WriteLine(x.FirstName + " " + x.LastName);
            }

            Console.WriteLine(orders2.Sum(order => order.OrderItems.Select(item =>(double)(item.QtyOrdered * item.Price)).Sum()));

【讨论】:

  • 在c#中一个更好的方法是Console.WriteLine("{0} {1}", x.FirstName, x.LastName);
  • 好的,我做到了,它有效。这有点难看,但是对于您和 Edwards cmets,我已将问题缩小到打印每个 .addProduct。我想这是 foreach 循环的一部分。我现在需要做的是破译如何让它每行打印一次,然后在底部显示总数。我将用我现在拥有的代码更新代码。
  • 你的意思是每个名字都有一行?
  • @nick-s 我已经尝试实现 Distinct() 但它仍在多次打印出来。参考您的其他评论,更新后的代码现在可以正确添加总数,尽管这可能是一种糟糕的方法。
  • 这是因为您的 select new 代码已更改为包含 Total,即使它具有相同的客户,每一行也会有所不同。
【解决方案2】:

看看你的代码的这个 .NET fiddle

https://dotnetfiddle.net/91yYMF

它展示了如何进行求和。你还有什么需要做的吗?

【讨论】:

  • 不确定您在说什么,该代码是我发布的。没有任何变化,它仍然没有输出正确的信息。
  • @The_fatness 我只是展示了另一种方法 - 请参阅Another way to do it部分我要求澄清正确信息是什么?因为我不是确定你要做什么
猜你喜欢
  • 2019-01-31
  • 2021-01-23
  • 1970-01-01
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
相关资源
最近更新 更多