Пример #1
0
        public static IEnumerable <Partition <TResult> > Split <TSource, TResult>(this IEnumerable <TSource> source, int maxSize, Func <TSource, TResult> selector, Func <TSource, bool> predicate = default)
        {
            if (source is null)
            {
                throw new ArgumentNullException(paramName: nameof(source));
            }
            else if (maxSize < 1)
            {
                throw new ArgumentOutOfRangeException(paramName: nameof(maxSize), message: FormatXResource(locator: typeof(ArgumentOutOfRangeException), subpath: "CanNotLessThanOne"));
            }
            else if (selector is null)
            {
                throw new ArgumentNullException(paramName: nameof(selector));
            }
            //
            TResult[] portion;
            var       partitionUpperBound = maxSize - 1;
            var       buffer          = new List <TResult>();
            var       bufferTailIndex = -1;
            var       partitionIndex  = -1;

            foreach (var item in source)
            {
                if (bufferTailIndex == partitionUpperBound)
                {
                    portion = new TResult[maxSize];
                    buffer.CopyTo(index: 0, array: portion, arrayIndex: 0, count: maxSize);
                    bufferTailIndex = -1;
                    yield return(new Partition <TResult>(elements: ListReadOnlyWrap <TResult> .WrapOrEmpty(list: portion), index: checked (++partitionIndex)));
                }
                if (predicate?.Invoke(item) ?? true)
                {
                    if (buffer.Count > ++bufferTailIndex)
                    {
                        buffer[bufferTailIndex] = selector(item);
                    }
                    else
                    {
                        buffer.Add(selector(item));
                    }
                }
            }
            if (bufferTailIndex > -1)
            {
                portion = new TResult[bufferTailIndex + 1];
                buffer.CopyTo(index: 0, array: portion, arrayIndex: 0, count: bufferTailIndex + 1);
                buffer.Clear();
                yield return(new Partition <TResult>(elements: ListReadOnlyWrap <TResult> .WrapOrEmpty(list: portion), index: checked (++partitionIndex)));
            }
            else
            {
                buffer.Clear();
            }
        }
Пример #2
0
 internal Partition(ListReadOnlyWrap <T> elements, int index)
 {
     if (index < 0)
     {
         throw new ArgumentOutOfRangeException(paramName: nameof(index));
     }
     else if (elements is null)
     {
         throw new ArgumentNullException(paramName: nameof(elements));
     }
     //
     Index    = index;
     Elements = elements;
 }