Подтвердить что ты не робот

LINQ изначально поддерживает разделение коллекции на две части?

Учитывая набор элементов, как мне разбить коллекцию на 2 подкатегории на основе предиката?

Вы можете делать 2 В тех случаях, когда выполняется поиск, но тогда время выполнения равно 2 * N (которое, хотя и O (n), занимает в два раза больше и, очевидно, не является предпочтительным)

IEnumerable<int> even = nums.Where(i => IsEven(i));
IEnumerable<int> odd = nums.Where(i => !IsEven(i));

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

public static void SplitOnPred<T>(
        this IEnumerable<T> collection,
        Func<T, bool> pred,
        out IEnumerable<T> trueSet,
        out IEnumerable<T> falseSet
    ) {
        List<T> trueSetList = new List<T>();
        List<T> falseSetList = new List<T>();
        foreach( T item in collection ) {
            if( pred( item ) ) {
                trueSetList.Add( item );
            } else {
                falseSetList.Add( item );
            }
        }
        trueSet = trueSetList;
        falseSet = falseSetList;
}

Вопрос: LINQ имеет встроенную поддержку для разбиения коллекции на один линейный проход?

4b9b3361

Ответ 1

Есть ли у LINQ встроенная поддержка для разбиения коллекции на один линейный проход?

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

Самый близкий встроенный метод будет GroupBy (или ToLookup). Вы можете группироваться нечетно или даже:

var groups = nums.GroupBy(i => IsEven(i));

Это разделится на две "группы" на основе того, являются ли цифры нечетными или четными.

Ответ 2

Ответ Рида Копси упоминает ToLookup, и это кажется привлекательным.

var lookup = nums.ToLookup(IsEven);

где IsEven - статический метод с ожидаемым сигналом и возвращаемым типом. Тогда

IEnumerable<int> even = lookup[true];
IEnumerable<int> odd = lookup[false];

Ответ 3

Хорошо, если логика является исключительной, в вашем случае вы можете сделать, например

var list = new List<int> {1,2,3,4,5,6,7,8,9,10};    
var result = list.GroupBy(x=> x%2==0);

и в result

foreach(var r in result)
{
    if(r.Key)
     //EVEN
    else 
     //ODD
}

Ответ 4

Если вы хотите поддержать отложенное выполнение, используйте функцию или расширение, например:

IEnumerable<T> Split<T>(this IEnumerable<T> source, out IEnumerable<T> odd)
{
   IList<T> oddCollector = new List<T>();
   Bool odd = true;
   foreach(T item in source)
   {
      if(odd)
      {
          oddCollector.Add(item);
      }
      else
      {
          yield return item;
      }
      odd = !odd;
   }
 }

Приношу извинения за любую небольшую ошибку компилятора, я сделал это из головы. Вместо четного/нечетного вы можете добавить предикат.