Exemplo n.º 1
0
        /// <summary>
        /// Joins elements of an outer option with elements of an inner option having matching keys.
        /// </summary>
        /// <typeparam name="TOuter">The type of the elements of <paramref name="outer"/>.</typeparam>
        /// <typeparam name="TInner">The type of the elements of <paramref name="inner"/>.</typeparam>
        /// <typeparam name="TKey">The type of the key used to match elements.</typeparam>
        /// <typeparam name="TResult">The type of the result value for each matched pair.</typeparam>
        /// <param name="outer">The outer option to join.</param>
        /// <param name="inner">The inner option to join.</param>
        /// <param name="outerKeySelector">
        /// A function to select the key that corresponds to an element of <paramref name="outer"/>.
        /// </param>
        /// <param name="innerKeySelector">
        /// A function to select the key that corresponds to an element of <paramref name="inner"/>.
        /// </param>
        /// <param name="resultSelector">A function to select a result value for each matched pair.</param>
        /// <param name="comparer">
        /// A comparer to determine whether keys are equal. (If <see langword="null"/>, <see
        /// cref="EqualityComparer{T}.Default"/> is used.)
        /// </param>
        /// <returns>
        /// An option that contains the result of applying <paramref name="resultSelector"/> to the
        /// element of <paramref name="outer"/> and the element of <paramref name="inner"/>, if both
        /// options are full and their corresponding keys are equal according to <paramref
        /// name="comparer"/>; otherwise, an empty option.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="outer"/>, <paramref name="inner"/>, <paramref name="outerKeySelector"/>,
        /// <paramref name="innerKeySelector"/>, or <paramref name="resultSelector"/> is <see langword="null"/>.
        /// </exception>
        public static IOpt <TResult> Join <TOuter, TInner, TKey, TResult>(this IOpt <TOuter> outer, IOpt <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, TInner, TResult> resultSelector, IEqualityComparer <TKey> comparer)
        {
            if (outer == null)
            {
                throw new ArgumentNullException(nameof(outer));
            }
            if (inner == null)
            {
                throw new ArgumentNullException(nameof(inner));
            }
            if (outerKeySelector == null)
            {
                throw new ArgumentNullException(nameof(outerKeySelector));
            }
            if (innerKeySelector == null)
            {
                throw new ArgumentNullException(nameof(innerKeySelector));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(outer
                   .CrossJoinRaw(inner)
                   .WhereRaw(x => comparer.DefaultIfNull().Equals(outerKeySelector(x.first), innerKeySelector(x.second)))
                   .SelectRaw(x => resultSelector(x.first, x.second)));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Joins each element of an outer option to a grouping of inner elements with matching keys,
        /// then applies a transform to each grouping.
        /// </summary>
        /// <typeparam name="TOuter">The type of the elements of <paramref name="outer"/>.</typeparam>
        /// <typeparam name="TInner">The type of the elements of <paramref name="inner"/>.</typeparam>
        /// <typeparam name="TKey">The type of the key used to match and group elements.</typeparam>
        /// <typeparam name="TResult">The type of the result value for each grouping.</typeparam>
        /// <param name="outer">The outer option to join.</param>
        /// <param name="inner">The inner option to join.</param>
        /// <param name="outerKeySelector">
        /// A function to select the key that corresponds to an element of <paramref name="outer"/>.
        /// </param>
        /// <param name="innerKeySelector">
        /// A function to select the key that corresponds to an element of <paramref name="inner"/>.
        /// </param>
        /// <param name="resultSelector">A function to select a result value for each grouping.</param>
        /// <param name="comparer">
        /// A comparer to determine whether keys are equal. (If <see langword="null"/>, <see
        /// cref="EqualityComparer{T}.Default"/> is used.)
        /// </param>
        /// <returns>
        /// An option that contains the result of applying <paramref name="resultSelector"/> to the
        /// grouping for the element of <paramref name="outer"/> and its corresponding elements of
        /// <paramref name="inner"/>, if <paramref name="outer"/> is full; otherwise, an empty option.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="outer"/>, <paramref name="inner"/>, <paramref name="outerKeySelector"/>,
        /// <paramref name="innerKeySelector"/>, or <paramref name="resultSelector"/> is <see langword="null"/>.
        /// </exception>
        public static IOpt <TResult> GroupJoin <TOuter, TInner, TKey, TResult>(this IOpt <TOuter> outer, IOpt <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, IOpt <TInner>, TResult> resultSelector, IEqualityComparer <TKey> comparer)
        {
            if (outer == null)
            {
                throw new ArgumentNullException(nameof(outer));
            }
            if (inner == null)
            {
                throw new ArgumentNullException(nameof(inner));
            }
            if (outerKeySelector == null)
            {
                throw new ArgumentNullException(nameof(outerKeySelector));
            }
            if (innerKeySelector == null)
            {
                throw new ArgumentNullException(nameof(innerKeySelector));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(outer.SelectRaw(outerValue =>
            {
                var comparerNonNull = comparer.DefaultIfNull();
                var outerKey = outerKeySelector(outerValue);
                var innerValues = inner.WhereOptRaw(innerValue => comparerNonNull.Equals(outerKey, innerKeySelector(innerValue)));
                return resultSelector(outerValue, innerValues);
            }));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Determines whether an option has an equal length and sequence of elements to a sequence.
        /// </summary>
        /// <typeparam name="TSource">
        /// The type of the elements of <paramref name="first"/> and <paramref name="second"/>.
        /// </typeparam>
        /// <param name="first">A source option.</param>
        /// <param name="second">A sequence whose contents to compare with those of <paramref name="first"/>.</param>
        /// <param name="comparer">
        /// A comparer to determine whether values are equal. (If <see langword="null"/>, <see
        /// cref="EqualityComparer{T}.Default"/> is used.)
        /// </param>
        /// <returns>
        /// <see langword="true"/> if <paramref name="first"/> and <paramref name="second"/> are both
        /// empty or each of <paramref name="first"/> and <paramref name="second"/> contains exactly
        /// one element and those elements are equal; otherwise, <see langword="false"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="first"/> or <paramref name="second"/> is null.
        /// </exception>
        public static bool SequenceEqual <TSource>(this IOpt <TSource> first, IEnumerable <TSource> second, IEqualityComparer <TSource> comparer)
        {
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }
            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }

            var opt = first.ToFixed();

            if (opt.HasValue)
            {
                using (var secondEnumerator = second.GetEnumerator())
                {
                    if (secondEnumerator.MoveNext())
                    {
                        var onlyValue = secondEnumerator.Current;

                        if (!secondEnumerator.MoveNext())
                        {
                            // second is same length
                            return(comparer.DefaultIfNull().Equals(opt.ValueOrDefault, onlyValue));
                        }
                    }
                }

                // Number of elements did not match
                return(false);
            }
            else
            {
                using (var secondEnumerator = second.GetEnumerator())
                {
                    return(!secondEnumerator.MoveNext());
                }
            }
        }