2010-05-12 3 views
0

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

В основном я хочу отфильтровать список на основе какого-то предиката и вызывать только Distinct() на этом подмножестве, но также рекомбинировать с перечислением, где предикат возвращает false.

Может ли кто-нибудь подумать о хорошем идиоматическом способе Linq для этого? Я полагаю, что вопрос сводится к следующему:

С Linq, как вы можете выполнять выборочную обработку на основе заданного перечисления и рекомбинировать поток результатов с отклоненными случаями из предиката?

ответ

0

Вы можете сделать это, пройдя список дважды, один раз, чтобы применить предикат и дедукцию, и второй раз применить отрицание предиката. Другим решением является написать свой собственный вариант метода Where расширения, который выталкивает записи несовпадающих в буфер на стороне:

IEnumerable<T> WhereTee(this IEnumerable<T> input, Predicate<T> pred, List<T> buffer) 
{ 
    foreach (T t in input) 
    { 
     if (pred(t)) 
     { 
      yield return t; 
     } 
     else 
     { 
      buffer.Add(t); 
     } 
    } 
} 
0

Можете ли вы дать немного больше информации о том, как вы хотели бы, чтобы рекомбинировать элементов, входящих.

Один из способов решения этой проблемы - использование Zip-оператора .Net 4.0, как это.

var initialList = new List<int>(); 

    var resjectedElemnts = initialList.Where(x=> !aPredicate(x)); 
    var accepetedElements = initialList.Where(x=> aPredicate(x)); 

    var result = accepetedElements.Zip(resjectedElemnts,(accepted,rejected) => T new {accepted,rejected}); 

Это создаст список пары отвергнутых и accepeted элементов. Но размер списка будет зависеть от более короткого списка между двумя входами.