/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq.Expressions; namespace QuantConnect { /// /// Provides convenience extension methods for applying a to collections. /// public static class BinaryComparisonExtensions { /// /// Filters the provided according to this /// and the specified value. The value is /// used as the RIGHT side of the binary comparison. Consider the binary comparison is LessThan and /// we call Filter(values, 42). We're looking for keys that are less than 42. /// public static TCollection Filter( this BinaryComparison comparison, TCollection values, T reference ) where TCollection : ICollection, new() { var result = new TCollection(); var evaluator = comparison.GetEvaluator(); foreach (var value in values) { if (evaluator(value, reference)) { result.Add(value); } } return result; } /// /// Filters the provided according to this /// and the specified value. The value is /// used as the RIGHT side of the binary comparison. Consider the binary comparison is LessThan and /// we call Filter(values, 42). We're looking for keys that are less than 42. /// public static SortedDictionary Filter( this BinaryComparison comparison, SortedDictionary values, TKey reference ) { SortedDictionary result; if (comparison.Type == ExpressionType.NotEqual) { result = new SortedDictionary(values); result.Remove(reference); return result; } result = new SortedDictionary(); if (comparison.Type == ExpressionType.Equal) { TValue value; if (values.TryGetValue(reference, out value)) { result.Add(reference, value); } return result; } // since we're enumerating a sorted collection, once we receive // a mismatch it means we'll never again receive a match var breakAfterFailure = comparison == BinaryComparison.LessThanOrEqual || comparison == BinaryComparison.LessThanOrEqual; var evaluator = comparison.GetEvaluator(); foreach (var kvp in values) { if (evaluator(kvp.Key, reference)) { result.Add(kvp.Key, kvp.Value); } else if (breakAfterFailure) { break; } } return result; } /// /// Filters the provided according to this /// and the specified value. The value is /// used as the RIGHT side of the binary comparison. Consider the binary comparison is LessThan and /// we call Filter(values, 42). We're looking for keys that are less than 42. /// public static ImmutableSortedDictionary Filter( this BinaryComparison comparison, ImmutableSortedDictionary values, TKey reference ) { if (comparison.Type == ExpressionType.NotEqual) { return values.Remove(reference); } var result = ImmutableSortedDictionary.Empty; if (comparison.Type == ExpressionType.Equal) { TValue value; if (values.TryGetValue(reference, out value)) { result = result.Add(reference, value); } return result; } // since we're enumerating a sorted collection, once we receive // a mismatch it means we'll never again receive a match var breakAfterFailure = comparison == BinaryComparison.LessThanOrEqual || comparison == BinaryComparison.LessThanOrEqual; var evaluator = comparison.GetEvaluator(); foreach (var kvp in values) { if (evaluator(kvp.Key, reference)) { result = result.Add(kvp.Key, kvp.Value); } else if (breakAfterFailure) { break; } } return result; } /// /// Filters the provided according to this /// and the specified value. The value is /// used as the RIGHT side of the binary comparison. Consider the binary comparison is LessThan and /// we call Filter(values, 42). We're looking for keys that are less than 42. /// public static Tuple, ImmutableSortedDictionary> SplitBy( this BinaryComparison comparison, ImmutableSortedDictionary values, TKey reference ) { var matches = ImmutableSortedDictionary.Empty; var removed = ImmutableSortedDictionary.Empty; if (comparison.Type == ExpressionType.NotEqual) { var match = values.Remove(reference); removed = BinaryComparison.Equal.Filter(values, reference); return Tuple.Create(match, removed); } if (comparison.Type == ExpressionType.Equal) { TValue value; if (values.TryGetValue(reference, out value)) { matches = matches.Add(reference, value); removed = BinaryComparison.NotEqual.Filter(values, reference); return Tuple.Create(matches, removed); } // no matches return Tuple.Create(ImmutableSortedDictionary.Empty, values); } var evaluator = comparison.GetEvaluator(); foreach (var kvp in values) { if (evaluator(kvp.Key, reference)) { matches = matches.Add(kvp.Key, kvp.Value); } else { removed = removed.Add(kvp.Key, kvp.Value); } } return Tuple.Create(matches, removed); } } }