2015-02-27 2 views
1

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

Структура нечто похожее на:

public class A 
{ 
    int id {get; set;} 
    int recId {get; set;} 
    string category {get; set;} 
} 


public class B 
{ 
    int recId {get; set;} 
    string category {get; set;} 
} 

До сих пор у меня есть следующий кусок LINQ, чтобы дать мне мою коллекцию недостающих записей, но это только дает мне никакого recId, что отсутствует:

var noLongerHaveRecordInCollectionB = 
CollectionA.Select(x => x.recId).Except(CollectionB.Select(x => x.recId)); 

мне нужно List<A> каждой записи которых:

1.) больше не имеет recId провел в го e CollectionB. не

ИЛИ

2.) больше не имеет запись, которая имеет соответствие recId и category в CollectionB

Для примера вполне возможно, что в пределах CollectionA есть 2 записи с одинаковыми recId, но разными category.

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

Так что главный вопрос заключается в том, как я могу заполнить noLongerHaveRecordInCollectionB со всеми <T> элементов а, которые были проверены на CollectionB, а не только recId, как это в настоящее время делает, я хочу, чтобы весь объект.

редактирование: вход/результат

CollectionA

1,2254, категории А

2,2236, категории А

3,2415, категория B

4,1275, Категория B < --- то же лицо, что и ниже, разн категории

5,1275, Категория C < --- тот же человек, как и выше, разн категория

CollectionB

2254, Категория А

2415, Категория B

1275 Категория C

Ожидаемый R esult

Я хотел бы ожидать (от CollectionA) следующие идентификаторы, которые будут выделены в моем списке для удаления: 2, 4

+0

'CollectionA.Where (х => CollectionB.Select (у => y.recId) .Contains (x.recId)) 'даст вам записи, а не только идентификаторы. – Alexander

+0

Это не относится к категории? – JsonStatham

+1

Вы всегда можете использовать методы набора, такие как 'Enumerable.Except' и использовать другой метод set' Join', чтобы получить полные данные. –

ответ

2

Вы можете просто получить то, что хотите, с помощью Where с условием ||. Не нужно идти на комплексное решение.

var result = collectionA.Where(a => collectionB.Any(b => a.recId == b.recId && a.Category != b.Category) 
       || !collectionB.Any(b => b.recId == a.recId)); 

OLD ОТВЕТ

Вы можете реализовать IEqualityComparer для вашего класса и сравнить объекты на основе полей вы заинтересованы.Например реализовать метод Equals так:

public bool Equals(A a, B b) 
{ 
    return a.recId == b.recId && a.category == b.category ; 
} 

Тогда просто позвоните, кроме метода и передать ваши comparer:

var resultList = CollectionA .Except(CollectionB, new MyEqualityComparer()); 

Или, если вы реализуете его на классе, вместо отдельного comparer вы можете просто звоните Except:

var resultList = CollectionA .Except(CollectionB); 

Имейте в виду, что вам необходимо также реализовать GetHashCode метод.

UPDATE

Если вы хотите, чтобы пойти с IEqualityComparer<T> вы можете создать новый список из второго списка:

var secondListA = CollectionB.Select(x=> new A(){Category=x.Category, recId=x.recId}); 

А затем создать Comparer:

sealed class MyComparer : IEqualityComparer<A> 
{ 
    public bool Equals(A x, A y) 
    { 
     if (x == null) 
      return y == null; 
     else if (y == null) 
      return false; 
     else 
      return x.recId== y.recId&& x.Category == y.Category; 
    } 

    public int GetHashCode(A obj) 
    { 
     return obj.recId.GetHashCode(); 
    } 
} 

И используйте Except() перегрузку, которая производит заданное различие двух последовательностей с помощью usin г указанный IEqualityComparer<T> для сравнения значений .:

var result = CollectionA.Except(secondListA, new MyComparer()); 

Но я думаю, что вы должны пойти с простым Where фильтром как создание нового списка A типа может вызвать много overhade производительности.

+0

Как реализовать метод GetHashCode? – JsonStatham

+0

return obj.GetHashCode(); ????? – JsonStatham

0

Вы всегда можете использовать набор методов, как Enumerable.Except и использовать другой набор методу Join, чтобы получить полный данные.

мне нужно List<A> каждой записи, которая: 1. ) больше не имеет recId провел в CollectionB. не

var onlyInA = CollectionA.Select(x => x.recId).Except(CollectionB.Select(x => x.recId)); 
var dataOnlyInA = from a in CollectionA 
        join recId in onlyInA 
        on a.onlyInA equals recId 
        select a; 
List<A> result = dataOnlyInA.ToList(); 

2.) больше не имеет записи, который имеет соответствующий recId и category в CollectionB

Maybe:

var canBeRemovedFromA = CollectionA 
    .Where(a => CollectionB.Any(b => a.recID == b.recId && a.category!= b.category)); 

это не проверить, есть по крайней мере, одна соответствующая категория. Не ясно, нужно ли это.

+0

Я обновил вопрос сейчас, это яснее? – JsonStatham

Смежные вопросы