Как сделать пользовательское сравнение для каждого элемента в пересечении двух коллекций

2

Если у меня есть:

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

и выполните:

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

Как мне получить:

CrewBase left;
CrewBase right;

:

intersect

поэтому я могу перебрать все CrewBases в Intersect и сделать вызов:

Action(left,right);

Я только хочу сделать это на CrewBases, которые равны в обоих списках в соответствии с моим CrewBaseComparer.OnId, который реализует:

IEqualityComparer<CrewBase>

Это моя текущая реализация:

    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;
    }
  • 0
    Может быть полезно уточнить, на что ссылается CrewBaseComparer.OnID () ... при условии, что вы используете универсальный IEnumerable .NET 4.0, в котором для всех форм вызова Intersect, которые я вижу в документах MSDN, требуется, чтобы второй аргумент Intersect был ссылка на IEqualityComparer?
  • 0
    CrewBaseBaseComparer.OnID () - это IEqualityComparer <CrewBase>, который сравнивается только с CrewBase.ID. Это делается для того, чтобы все объекты CrewBase, имеющие одинаковый идентификатор, но не обязательно, были равны в CrewBase.Equal ().
Теги:
linq

2 ответа

5

Вам нужно будет определить класс, который реализует 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
}

а затем вызовите Intersect с экземпляром вашего класса:

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

Не обязательно, чтобы Intersect всегда передавал элемент из "left" и элемент из "right" в качестве параметров "x" и "y" соответственно, но это не ясно из вашего вопроса, если это имеет значение.

Основываясь на вашем обновлении, похоже, что вам нужно сделать Join:

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);
}

В этом соединении мы рассматриваем каждый элемент как ключ и используем существующий пользовательский IEqualityComparer для сравнения экземпляров. Селектор результатов для соединения возвращает анонимный тип со свойствами "left" и "right", соответствующими элементам из левой и правой коллекций. Затем вы можете перебрать результат, чтобы выполнить свое действие.

  • 0
    Я обновил вопрос.
  • 0
    Я не понимаю вашу формулировку: «Это не обязательно тот случай, когда Intersect всегда будет передавать элемент из« left »и элемент из« right »как параметры« x »и« y »соответственно, но это не ясно из вашего вопроса если это имеет значение. Разве метод Intersect не возвращает те же левые объекты, что и соединение?
Показать ещё 1 комментарий
1

Я думаю, что у вас может быть неправильное представление о пересечении. Если вы берете пересечение двух списков, как кажется, что вы делаете, результатом будет один список, содержащий все элементы, которые находятся в обоих списках.

Таким образом, как только вы сделали

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

IEnumerable в пересечении не нуждается в левом или правом.

Однако, если то, что вы пытаетесь сделать, это получить влево и вправо в вашем пользовательском IEqualityComparer, тогда вы хотите, чтобы объект выглядел примерно так:

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню