/// <summary> /// Groups elements using key computed from the key selector. /// </summary> /// <param name="keySelector">Key selector lambda.</param> /// <returns>Elements grouped based on the provided key.</returns> public QueryCollectionValue GroupBy(Func <QueryValue, QueryValue> keySelector) { if (this.IsNull) { return(new QueryCollectionValue(this.Type.ElementType.CreateCollectionType(), this.EvaluationStrategy, this.EvaluationError, null)); } var keys = this.Elements.Select(keySelector).ToList(); var keyCollection = new QueryCollectionValue(this.Type.ElementType.CreateCollectionType(), this.EvaluationStrategy, this.EvaluationError, keys); var distinctKeys = keyCollection.Distinct().Elements; var elementType = this.Type.ElementType; var groupings = distinctKeys.Select(key => { if (key.IsNull) { var matchingNullElements = this.Elements.Where(element => keySelector(element).IsNull); return(this.CreateGroupingValue(key, QueryCollectionValue.Create(elementType, matchingNullElements.ToArray()))); } else { return(this.CreateGroupingValue(key, QueryCollectionValue.Create(elementType, this.Elements.Where(element => this.ValuesAreEqual(keySelector(element), key)).ToArray()))); } }); var keyType = keySelector(elementType.NullValue).Type; var groupingType = new QueryGroupingType(keyType, elementType, this.EvaluationStrategy); return(new QueryCollectionValue(groupingType.CreateCollectionType(), this.EvaluationStrategy, QueryError.GetErrorFromValues(groupings), groupings.Cast <QueryValue>())); }
/// <summary> /// Returns the first collection without the common elements from both input collections. /// </summary> /// <param name="collection">The input collection for the except operation</param> /// <returns>The firt collection with commmon elements removed.</returns> public QueryCollectionValue Except(QueryCollectionValue collection) { var resultValues = new List <QueryValue>(); foreach (QueryValue element in this.Elements) { if (!collection.Elements.Any(v => this.ValuesAreEqual(v, element))) { resultValues.Add(element); } } // except removes duplicates from the result, so applying distinct at the end var exceptResult = new QueryCollectionValue(this.Type, this.EvaluationStrategy, QueryError.GetErrorFromValues(resultValues), resultValues); var result = exceptResult.Distinct(); return(result); }