查找两个.NET DataTable的交集

时间:2021-07-14 22:58:10

Is there a relatively straightforward way to get the intersection of two DataTables in .NET?

是否有一种相对简单的方法来获取.NET中两个DataTable的交集?

I can think of the obvious ways (iterating over both tables myself in O(n^2)), but I'd like something a little more elegant if it's available. I suspect there may be an intelligent way that I'm not seeing. Readability and maintainability are important, of course, so I'm trying to stay away from anything too "slick".

我可以想到明显的方法(在O(n ^ 2)中自己迭代这两个表),但是如果它可用,我想要更优雅的东西。我怀疑可能有一种我没有看到的聪明方式。当然,可读性和可维护性很重要,所以我试图远离任何太“光滑”的东西。

Any good ideas?

有什么好主意吗?

EDIT: It looks like Bryan Watts has a pretty great solution for 3.5, but unfortunately I'm in .NET 2.0 (which I should have mentioned.)

编辑:看起来布莱恩沃茨有一个非常好的3.5解决方案,但不幸的是我在.NET 2.0(我应该提到。)

4 个解决方案

#1


With .NET 3.5:

使用.NET 3.5:

using System.Data;

public static class DataTableExtensions
{
    public static IEnumerable<DataRow> Intersect(this DataTable table, DataTable other)
    {
        return table.AsEnumerable().Intersect(other.AsEnumerable());
    }

    public static IEnumerable<DataRow> Intersect(this DataTable table, DataTable other, IEqualityComparer<DataRow> comparer)
    {
        return table.AsEnumerable().Intersect(other.AsEnumerable(), comparer);
    }
}

#2


Saw this example on MSDN which you may find useful. Its using the LINQ syntax.

在MSDN上看到这个你可能会觉得有用的例子。它使用LINQ语法。

DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];
DataTable details = ds.Tables["SalesOrderDetail"];

var query =
    from order in orders.AsEnumerable()
    join detail in details.AsEnumerable()
    on order.Field<int>("SalesOrderID") equals
        detail.Field<int>("SalesOrderID")
    where order.Field<bool>("OnlineOrderFlag") == true
    && order.Field<DateTime>("OrderDate").Month == 8
    select new
    {
        SalesOrderID =
            order.Field<int>("SalesOrderID"),
        SalesOrderDetailID =
            detail.Field<int>("SalesOrderDetailID"),
        OrderDate =
            order.Field<DateTime>("OrderDate"),
        ProductID =
            detail.Field<int>("ProductID")
    };


foreach (var order in query)
{
    Console.WriteLine("{0}\t{1}\t{2:d}\t{3}",
        order.SalesOrderID,
        order.SalesOrderDetailID,
        order.OrderDate,
        order.ProductID);
}

#3


Since you are using .NET 2.0, you should look at re-implementing the Intersect method.

由于您使用的是.NET 2.0,因此应该重新实现Intersect方法。

This psuedo-code should be very helpful for you.

这个伪代码应该对你非常有帮助。

#4


protected void Page_Load(object sender, EventArgs e) {

protected void Page_Load(object sender,EventArgs e){

    DataTable dt1 = new DataTable();

    dt1.Columns.Add("ColX", typeof(int));

    DataTable dt2 = new DataTable();

    dt2.Columns.Add("ColX", typeof(int));

    for (int i = 1; i <= 5; i++)
    {
        DataRow row = dt1.NewRow();

        row["ColX"] = 5 + i;

        dt1.Rows.Add(row);

        row = dt2.NewRow();

        row["ColX"] = 9 + i;
        dt2.Rows.Add(row);
    }


    intesect(dt1, dt2);

}


public void intesect(DataTable contacts1, DataTable contacts2)
{
    var contacts = contacts1.AsEnumerable().Intersect(contacts2.AsEnumerable(), DataRowComparer.Default);


    foreach (DataRow row in contacts)
    {
        Response.Write(row["ColX"]);
    }
}

#1


With .NET 3.5:

使用.NET 3.5:

using System.Data;

public static class DataTableExtensions
{
    public static IEnumerable<DataRow> Intersect(this DataTable table, DataTable other)
    {
        return table.AsEnumerable().Intersect(other.AsEnumerable());
    }

    public static IEnumerable<DataRow> Intersect(this DataTable table, DataTable other, IEqualityComparer<DataRow> comparer)
    {
        return table.AsEnumerable().Intersect(other.AsEnumerable(), comparer);
    }
}

#2


Saw this example on MSDN which you may find useful. Its using the LINQ syntax.

在MSDN上看到这个你可能会觉得有用的例子。它使用LINQ语法。

DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];
DataTable details = ds.Tables["SalesOrderDetail"];

var query =
    from order in orders.AsEnumerable()
    join detail in details.AsEnumerable()
    on order.Field<int>("SalesOrderID") equals
        detail.Field<int>("SalesOrderID")
    where order.Field<bool>("OnlineOrderFlag") == true
    && order.Field<DateTime>("OrderDate").Month == 8
    select new
    {
        SalesOrderID =
            order.Field<int>("SalesOrderID"),
        SalesOrderDetailID =
            detail.Field<int>("SalesOrderDetailID"),
        OrderDate =
            order.Field<DateTime>("OrderDate"),
        ProductID =
            detail.Field<int>("ProductID")
    };


foreach (var order in query)
{
    Console.WriteLine("{0}\t{1}\t{2:d}\t{3}",
        order.SalesOrderID,
        order.SalesOrderDetailID,
        order.OrderDate,
        order.ProductID);
}

#3


Since you are using .NET 2.0, you should look at re-implementing the Intersect method.

由于您使用的是.NET 2.0,因此应该重新实现Intersect方法。

This psuedo-code should be very helpful for you.

这个伪代码应该对你非常有帮助。

#4


protected void Page_Load(object sender, EventArgs e) {

protected void Page_Load(object sender,EventArgs e){

    DataTable dt1 = new DataTable();

    dt1.Columns.Add("ColX", typeof(int));

    DataTable dt2 = new DataTable();

    dt2.Columns.Add("ColX", typeof(int));

    for (int i = 1; i <= 5; i++)
    {
        DataRow row = dt1.NewRow();

        row["ColX"] = 5 + i;

        dt1.Rows.Add(row);

        row = dt2.NewRow();

        row["ColX"] = 9 + i;
        dt2.Rows.Add(row);
    }


    intesect(dt1, dt2);

}


public void intesect(DataTable contacts1, DataTable contacts2)
{
    var contacts = contacts1.AsEnumerable().Intersect(contacts2.AsEnumerable(), DataRowComparer.Default);


    foreach (DataRow row in contacts)
    {
        Response.Write(row["ColX"]);
    }
}