解析2个列表并创建一个比较表

时间:2019-05-22 17:15:00

标签: c# list linq

我正在使用一个屏幕,基本上可以比较2 lists

我有一个类RateFactorItem,其中包含一个Name属性和一个ProductValues列表。

public class RateFactorItem
    {
        public string Name { get; set; }

        public List<ProductValues> ProductValues { get; set; }
    }

ProductValues类的定义为:

public class ProductValues
    {
        public string ProductName { get; set; }
        public double? Value { get; set; }
    }

我还有一个名为CompareViewModel的类,用于填充比较屏幕。

public class CompareViewModel
    {
        public string ColumnName { get; set; }
        public double? VersionA { get; set; }
        public double? VersionB { get; set; }
        public double? Variance { get; set; }
    }

现在我有2个RateFactorItem列表,使用几种方法填充,示例代码如下。

public static List<RateFactorItem> GetRecordsA()
        {
            var items = new List<RateFactorItem>
            {
                new RateFactorItem
                {
                    Name = "Item1",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=200},
                    new ProductValues{ ProductName="product2", Value=300},
                    new ProductValues{ ProductName="product3", Value=400},
                    new ProductValues{ ProductName="product4", Value=500},
                    new ProductValues { ProductName = "product5", Value = 1000 },
                }
                },

                new RateFactorItem
                {
                    Name = "Item2",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=250},
                    new ProductValues{ ProductName="product2", Value=350},
                    new ProductValues{ ProductName="product3", Value=450},
                    new ProductValues{ ProductName="product4", Value=550},
                    new ProductValues { ProductName = "product5", Value = 1050 },
                }
                },

                new RateFactorItem
                {
                    Name = "Item3",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=2300},
                    new ProductValues{ ProductName="product2", Value=3030},
                    new ProductValues{ ProductName="product3", Value=4040},
                    new ProductValues{ ProductName="product4", Value=5030},
                    new ProductValues { ProductName = "product5", Value = 1400 },
                }
                },

                new RateFactorItem
                {
                    Name = "ItemX",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=20},
                    new ProductValues{ ProductName="product2", Value=30},
                    new ProductValues{ ProductName="product3", Value=40},
                    new ProductValues{ ProductName="product4", Value=50 },
                    new ProductValues { ProductName = "product5", Value = 60 },
                }
                }
            };

            return items;
        }

        public static List<RateFactorItem> GetRecordsB()
        {
            var items = new List<RateFactorItem>
            {
                new RateFactorItem
                {
                    Name = "Item1",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=230},
                    new ProductValues{ ProductName="product2", Value=340},
                    new ProductValues{ ProductName="product3", Value=470},
                    new ProductValues{ ProductName="product4", Value=590},
                    new ProductValues { ProductName = "product5", Value = 1010 },
                }
                },

                new RateFactorItem
                {
                    Name = "Item2",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=220},
                    new ProductValues{ ProductName="product2", Value=370},
                    new ProductValues{ ProductName="product3", Value=400},
                    new ProductValues{ ProductName="product4", Value=510},
                    new ProductValues { ProductName = "product5", Value = 150 },
                }
                },

                new RateFactorItem
                {
                    Name = "Item3",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=2900},
                    new ProductValues{ ProductName="product2", Value=3930},
                    new ProductValues{ ProductName="product3", Value=4940},
                    new ProductValues{ ProductName="product4", Value=5930},
                    new ProductValues { ProductName = "product5", Value = 1900 },
                }
                },

                new RateFactorItem
                {
                    Name = "ItemY",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=40},
                    new ProductValues{ ProductName="product2", Value=80},
                    new ProductValues{ ProductName="product3", Value=90},
                    new ProductValues{ ProductName="product4", Value=60 },
                    new ProductValues { ProductName = "product5", Value = 70 },
                }
                }
            };

            return items;
        }

在控制器操作方法中,我尝试创建CompareViewModel的列表并按如下所示填充UI:

public IActionResult Index()
        {
            var model = new List<CompareViewModel>();

            var productNameA = "product1";
            var productNameB = "product1";

            var recordsA = Records.GetRecordsA();
            var recordsB = Records.GetRecordsB();

            var countA = recordsA.Count();
            var countB = recordsB.Count();

            for (int i = 0; i < Math.Max(countA, countB); i++)
            {
                var itemName = countA > countB ? recordsA[i].Name : recordsB[i].Name;
                var recordA = recordsA.Where(x => x.Name == itemName)?.FirstOrDefault();
                var recordB = recordsB.Where(x => x.Name == itemName)?.FirstOrDefault();

                var subModel = new CompareViewModel
                {
                    ColumnName = itemName,
                    VersionA = recordA != null ? (recordA.ProductValues.Where(x => x.ProductName == productNameA).FirstOrDefault()?.Value ?? 0) : 0,
                    VersionB = recordB != null ? (recordB.ProductValues.Where(x => x.ProductName == productNameB).FirstOrDefault()?.Value ?? 0) : 0,
                    Variance = ((recordA != null ? (recordA.ProductValues.Where(x => x.ProductName == productNameA).FirstOrDefault()?.Value ?? 0) : 0) - (recordB != null ? (recordB.ProductValues.Where(x => x.ProductName == productNameB).FirstOrDefault()?.Value ?? 0) : 0))
                };
                model.Add(subModel);
            }

            return View(model);
        }

出于演示目的,我在recordsArecordsB中的项目数相同,但是在实时情况下,项目数可以不同。

在上面的示例中,比较屏幕填充如下:

Image 1

仅显示共同的项目Item1,Item2,Item3,而在屏幕上仅显示1个不常见的项目。 我希望所有常见和不常见的记录都应显示在网格中,显然,不常见的记录的相对应记录为零,如下所示:

Image2

因此,如果列表1有28条记录,列表2有32条记录,其中10条是公共记录,那么结果比较屏幕应显示10个公共记录和两个列表中的罕见记录。

我尝试使用IntersectExceptConcat运算符,但无法获得所需的结果。 请注意,RateFactorItem没有ID字段,因为这些字段从未存储在数据库中,而是全部在运行时计算并显示在屏幕上。

请协助指导。

1 个答案:

答案 0 :(得分:0)

我用结果构建了一个数据表

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            List<RateFactorItem> recordA = GetRecordsA();
            List<RateFactorItem> recordB = GetRecordsB();

            var results = (from a in recordA
                           join b in recordB on a.Name equals b.Name
                           select new { a = a, b = b, name = a.Name}
                           )
                           .Select(x => (from ap in x.a.ProductValues
                                         join bp in x.b.ProductValues on ap.ProductName equals bp.ProductName into abp
                                         from bp in abp.DefaultIfEmpty()
                                         select new { ap = ap, bp = bp, name = x.name }
                                         ).ToList()
                           ).ToList();
            DataTable dt = new DataTable();
            dt.Columns.Add("Item", typeof(string));
            dt.Columns.Add("product", typeof(string));
            dt.Columns.Add("A Quantity", typeof(int));
            dt.Columns.Add("B Quantity", typeof(int));
            dt.Columns.Add("Variance", typeof(int));

            foreach (var item in results)
            {
                foreach (var product in item)
                {
                    DataRow newRow = dt.Rows.Add(new object[] {
                        product.name,
                        product.ap.ProductName,
                        product.ap.Value,
                        product.bp.Value,
                        (product.bp.Value == null) ? (int)product.ap.Value : Math.Abs((int)product.ap.Value - (int)product.bp.Value)
                    });

                }
            }
            dataGridView1.DataSource = dt;

        }
        public static List<RateFactorItem> GetRecordsA()
        {
            var items = new List<RateFactorItem>
            {
                new RateFactorItem
                {
                    Name = "Item1",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=200},
                    new ProductValues{ ProductName="product2", Value=300},
                    new ProductValues{ ProductName="product3", Value=400},
                    new ProductValues{ ProductName="product4", Value=500},
                    new ProductValues { ProductName = "product5", Value = 1000 },
                }
                },

                new RateFactorItem
                {
                    Name = "Item2",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=250},
                    new ProductValues{ ProductName="product2", Value=350},
                    new ProductValues{ ProductName="product3", Value=450},
                    new ProductValues{ ProductName="product4", Value=550},
                    new ProductValues { ProductName = "product5", Value = 1050 },
                }
                },

                new RateFactorItem
                {
                    Name = "Item3",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=2300},
                    new ProductValues{ ProductName="product2", Value=3030},
                    new ProductValues{ ProductName="product3", Value=4040},
                    new ProductValues{ ProductName="product4", Value=5030},
                    new ProductValues { ProductName = "product5", Value = 1400 },
                }
                },

                new RateFactorItem
                {
                    Name = "ItemX",
                    ProductValues = new List<ProductValues>
                {
                    new ProductValues{ ProductName="product1", Value=20},
                    new ProductValues{ ProductName="product2", Value=30},
                    new ProductValues{ ProductName="product3", Value=40},
                    new ProductValues{ ProductName="product4", Value=50 },
                    new ProductValues { ProductName = "product5", Value = 60 },
                }
                }
            };

            return items;
        }

        public static List<RateFactorItem> GetRecordsB()
        {
            var items = new List<RateFactorItem>
            {
                new RateFactorItem
                {
                    Name = "Item1",
                    ProductValues = new List<ProductValues>
                    {
                        new ProductValues{ ProductName="product1", Value=230},
                        new ProductValues{ ProductName="product2", Value=340},
                        new ProductValues{ ProductName="product3", Value=470},
                        new ProductValues{ ProductName="product4", Value=590},
                        new ProductValues { ProductName = "product5", Value = 1010 },
                    }
                },

                new RateFactorItem
                {
                    Name = "Item2",
                    ProductValues = new List<ProductValues>
                    {
                        new ProductValues{ ProductName="product1", Value=220},
                        new ProductValues{ ProductName="product2", Value=370},
                        new ProductValues{ ProductName="product3", Value=400},
                        new ProductValues{ ProductName="product4", Value=510},
                        new ProductValues { ProductName = "product5", Value = 150 },
                    }
                },

                new RateFactorItem
                {
                    Name = "Item3",
                    ProductValues = new List<ProductValues>
                    {
                        new ProductValues{ ProductName="product1", Value=2900},
                        new ProductValues{ ProductName="product2", Value=3930},
                        new ProductValues{ ProductName="product3", Value=4940},
                        new ProductValues{ ProductName="product4", Value=5930},
                        new ProductValues { ProductName = "product5", Value = 1900 },
                    }
                    },

                new RateFactorItem
                {
                    Name = "ItemY",
                    ProductValues = new List<ProductValues>
                    {
                        new ProductValues{ ProductName="product1", Value=40},
                        new ProductValues{ ProductName="product2", Value=80},
                        new ProductValues{ ProductName="product3", Value=90},
                        new ProductValues{ ProductName="product4", Value=60 },
                        new ProductValues { ProductName = "product5", Value = 70 },
                    }
                 }
            };

            return items;
        }
    }
    public class RateFactorItem
    {
        public string Name { get; set; }

        public List<ProductValues> ProductValues { get; set; }
    }
    public class ProductValues
    {
        public string ProductName { get; set; }
        public double? Value { get; set; }
    }
}