tags:

views:

195

answers:

2

If I have:

IEnumerable<CrewBase> crewBasesLeft;
IEnumerable<CrewBase> crewBasesRight;

and do:

IEnumerable<CrewBase> intersect = crewBasesLeft
.Intersect( crewBasesRight,CrewBaseComparer.OnId() );

How do I get:

CrewBase left;
CrewBase right;

from the:

intersect

so I can loop over all the CrewBases in the Intersect and make a call:

Action(left,right);

I only want to do this on CrewBases that are equal in both list according to my CrewBaseComparer.OnId that implements:

IEqualityComparer<CrewBase>

This is my current implementation:

    IEnumerable<ObjectDifference> GetCrewBaseDifferences2( TrafficPlan left, TrafficPlan right )
    {
        var result = new List<ObjectDifference>();

        IEnumerable<CrewBase> intersect = left.CrewBases.Intersect( right.CrewBases,CrewBaseComparer.OnId() );

        foreach( CrewBase crewBase in intersect )
        {
            CrewBase other = crewBase;
            ObjectDifference diff = crewBase.GetDifference( right.CrewBases.First(x => x.Equals(other, CrewBaseComparer.OnId())) );
            if( diff.HasDifferences )
            {
                result.Add( diff );
            }
        }

        return result;
    }
+2  A: 

You'd have to define a class that implements IEqualityComparer:

class CustomComparer : IEqualityComparer<CrewBase>
{
    #region IEqualityComparer<CrewBase> Members

    public bool Equals(CrewBase x, CrewBase y)
    {
     return CustomCompare(x, y);
    }

    public int GetHashCode(CrewBase obj)
    {
     //a hash code based on the specific comparison
    }

    #endregion
}

and then call Intersect with an instance of your class:

IEnumerable<CrewBase> intersect = crewBasesLeft.Intersect(crewBasesRight, new CustomComparer());

It's not necessarily the case that Intersect will always pass an element from "left" and an element from "right" as parameters "x" and "y" respectively, but it's not clear from your question if that matters.

Based on your update, it looks like you need to do a Join instead:

IEnumerable<CrewBase> crewBasesLeft;
IEnumerable<CrewBase> crewBasesRight;

var Join = crewBasesLeft.Join(crewBasesRight, left => left, right => right, (left, right) => new { left, right }, CrewBaseComparer.OnId());

foreach (var i in Join)
{
    Action(i.left, i.right);
}

In this join, we treat each element as the key and use your existing custom IEqualityComparer to compare the instances. The result selector for the join returns an anonymous type with the properties "left" and "right" corresponding to elements from the left and right collections. Then, you may iterate over the result to perform your action.

Michael Petito
I updated the question.
Hakan Forss
I don't understand your statment:"It's not necessarily the case that Intersect will always pass an element from "left" and an element from "right" as parameters "x" and "y" respectively, but it's not clear from your question if that matters."Would the Intersect method not return the same left objects as the Join?
Hakan Forss
A set intersection contains distinct elements. From MSDN: "Intersect enumerates first [the first set], collecting all distinct elements of that sequence." The IEqualityComparer will be used to compare elements within the first set to establish a distinct set, and then used to compare elements between the distinct first and second sets. You cannot assume that the parameters x and y to the IEqualityComparer Equals method are from the left and right sets respectively. For example, they might both come from the left set.
Michael Petito
+1  A: 

I think you may have a bit of a misconception with an intersect. If you take the intersect of two lists, as it looks like you're doing, the result will be a single list that contains all of the elements that are in both of the lists.

Thus once you've done

IEnumerable<CrewBase> crewBasesLeft;
IEnumerable<CrewBase> crewBasesRight;
IEnumerable<CrewBase> intersect = crewBasesLeft.Intersect( crewBasesRight,CrewBaseComparer.OnId() );

The IEnumerable in intersect doesn't need left or right.

However, if what you're trying to do is get the left and right in your custom IEqualityComparer, then what you want is an object that looks something like this:

class CrewBaseIdComparer : IEqualityComparer<CrewBase>
{
    public bool Equals(CrewBase left, CrewBase right)
    {
        // your logic
    }

    public int GetHashCode(CrewBase item)
    {
        // your logic
    }
}
Gregg