比较两个DataTable并显示LINQ中另一个数据表的差异

时间:2014-12-12 08:31:07

标签: c# wpf linq

我有两个DataTables,我想显示行。如果两个数据表具有相同的值,则在所有列中标记X,否则选择具有最高值的列(例如:DT1:10,DT2:5)

Datatable1

id       Name      Weight
1        Ship       500
2        Train      600
3        Plane      700
4        Car        800

Datatable2

  id  Name       Weight
  1    Ship      500
  3    Plane     600
  4    Car       200

我希望结果是:

Datatable3

id    Name      Weight          Datatable1        Datatable2
  1   Ship      500              X                 X
  2   Train     600              X
  3   Plane     700              X                 X
  4   Car       800              X

我尝试过以下方法: -

 DataTable Datatable3 = (from a in Datatable1.AsEnumerable() 
                         join b in Datatable2.AsEnumerable() 
                         on a["Name"].ToString() equals b["Name"].ToString()
                         a["Weight"].ToString() equals b["Weight"].ToString() into g 
                         where g.Count() != 1 select a).CopyToDataTable();
 dataGrid1.ItemsSource = Datatable3.DefaultView;

请帮我解决这个问题。提前致谢

2 个答案:

答案 0 :(得分:1)

这就是我所拥有的: -

DataTable Datatable3 = dt1.AsEnumerable().Union(dt2.AsEnumerable())
         .GroupBy(x => x.Field<int>("Id"))
         .Select(x =>
             {
                 var topWeightItem = x.OrderByDescending(z => z.Field<int>  ("Weight")).First();
                  return new Items
                  {
                     Id = x.Key,
                     Name = topWeightItem.Field<string>("Name"),
                     Weight = topWeightItem.Field<int>("Weight"),
                     DataTable1 = dt1.AsEnumerable().Any(z => z.Field<int>("Id") == x.Key 
                                  && z.Field<int>("Weight") == topWeightItem.Field<int>("Weight")
                                  && z.Field<string>("Name") == topWeightItem.Field<string>("Name")) 
                                  ? "X" : String.Empty,
                     DataTable2 = dt2.AsEnumerable().Any(z => z.Field<int>("Id") == x.Key 
                                  && z.Field<int>("Weight") == topWeightItem.Field<int>("Weight") 
                                  && z.Field<string>("Name") == topWeightItem.Field<string>("Name")) 
                                  ? "X" : String.Empty
                    };
               }
         ).PropertiesToDataTable<Items>();

由于它返回了anonymous类型,因此您无法使用CopyToDataTable方法,因此请检查this以了解我如何将其转换为数据表。

我收到了这个输出: -

enter image description here

我使用以下类型进行转换: -

public class Items
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Weight { get; set; }
    public string DataTable1 { get; set; }
    public string DataTable2 { get; set; }
 }

答案 1 :(得分:0)

我写了两个查询来实现你所说的......也许你可以进一步优化它。

//datatable1
         DataTable dt1 = new DataTable();

        dt1.Columns.Add("Id");
        dt1.Columns.Add("Name");
        dt1.Columns.Add("Weight");

        DataRow dr ;

        dr = dt1.NewRow();
        dr["Id"] = 1;
        dr["Name"] = "Ship";
        dr["Weight"] = 500;
        dt1.Rows.Add(dr);


        dr = dt1.NewRow();
        dr["Id"] = 2;
        dr["Name"] = "Train";
        dr["Weight"] = 600;
        dt1.Rows.Add(dr);


        dr = dt1.NewRow();
        dr["Id"] = 3;
        dr["Name"] = "Plane";
        dr["Weight"] = 700;
        dt1.Rows.Add(dr);

        dr = dt1.NewRow();
        dr["Id"] = 4;
        dr["Name"] = "Car";
        dr["Weight"] = 400;
        dt1.Rows.Add(dr);

         //datatable2
        DataTable dt2 = new DataTable();
        dt2.Columns.Add("Id");
        dt2.Columns.Add("Name");
        dt2.Columns.Add("Weight");
        DataRow dr2;
        dr2 = dt2.NewRow();
        dr2["Id"] = 1;
        dr2["Name"] = "Ship";
        dr2["Weight"] = 500;
        dt2.Rows.Add(dr2);

        dr2 = dt2.NewRow();
        dr2["Id"] = 3;
        dr2["Name"] = "Plane";
        dr2["Weight"] = 700;
        dt2.Rows.Add(dr2);

        dr2 = dt2.NewRow();
        dr2["Id"] = 4;
        dr2["Name"] = "Car";
        dr2["Weight"] = 400;
        dt2.Rows.Add(dr2);

        //iterate through table1
        IEnumerable<DataRow> table1 = from r in dt1.AsEnumerable()
                                      select r;

        //iterate through table2
        IEnumerable<DataRow> table2 = from r in dt2.AsEnumerable()
                                      select r;

        Console.WriteLine("Id\tName\tWeight\tDatatable1\tDatatable2");
        Console.WriteLine("----------------------------------------------------");
        //prints the common records
        foreach (DataRow td1 in table1.Distinct())//Matches wholes of the Element Sequence inside IEnumerable
        {
            table2.Distinct().ToList().ForEach(td2 =>
            {
                if (td1.Field<string>("Id") == td2.Field<string>("Id"))
                {
                    Console.WriteLine(td1.Field<string>("Id") + "\t" + td1.Field<string>("Name") + "\t" + td1.Field<string>("Weight") + "\t" + "x" + "\t\t" + "x");
                }
            });
        }
        //prints the missing records
        var query = (from tb1 in dt1.AsEnumerable()
                     join tb2 in dt2.AsEnumerable()
                     on tb1.Field<string>("Id") equals tb2.Field<string>("Id") into subset
                     from sc in subset.DefaultIfEmpty()
                     where sc == null
                     select new
                     {
                         id = tb1.Field<string>("Id"),
                         name = tb1.Field<string>("Name"),
                         wt = tb1.Field<string>("Weight")
                     }).Distinct();

        foreach (var td1 in query)
        {
            Console.WriteLine(td1.id + "\t" + td1.name + "\t" + td1.wt + "\t" + "x" + "\t\t" + "-");
        }