/*
* 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);
}
}
}