tags:

views:

890

answers:

3

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

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".

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  A: 

With .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);
    }
}
Bryan Watts
This is a cool solution. +1
Perpetualcoder
This doesn't solve my particular problem, per se, but it's such an elegant solution to the question in general, which probably makes it useful for people searching on this problem, it has to earn "accepted" status. (I wish it could share it with your other answer...it would be nice to have both.)
Beska
A: 

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

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);
}
Perpetualcoder
+1  A: 

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

This psuedo-code should be very helpful for you.

Bryan Watts