Lean  $LEAN_TAG$
SortEnumerator.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15 */
16 
17 using System;
18 using System.Linq;
19 using QuantConnect.Util;
20 using QuantConnect.Data;
21 using System.Collections;
22 using System.Collections.Generic;
23 
25 {
26  /// <summary>
27  /// Provides an enumerator for sorting collections of <see cref="BaseData"/> objects based on a specified property.
28  /// The sorting occurs lazily, only when enumeration begins.
29  /// </summary>
30  /// <typeparam name="TKey">The type of the key used for sorting.</typeparam>
31  public sealed class SortEnumerator<TKey> : IEnumerator<BaseData>, IDisposable
32  {
33  private readonly IEnumerable<BaseData> _data;
34 #pragma warning disable CA2213 // call csutom DisposeSafely() in Dispose()
35  private IEnumerator<BaseData> _sortedEnumerator;
36 #pragma warning restore CA2213 // call csutom DisposeSafely() in Dispose()
37  private readonly Func<BaseData, TKey> _keySelector;
38 
39  /// <summary>
40  /// Initializes a new instance of the <see cref="SortEnumerator{TKey}"/> class.
41  /// </summary>
42  /// <param name="data">The collection of <see cref="BaseData"/> to enumerate over.</param>
43  /// <param name="keySelector">A function that defines the key to sort by. Defaults to sorting by <see cref="BaseData.EndTime"/>.</param>
44  public SortEnumerator(IEnumerable<BaseData> data, Func<BaseData, TKey> keySelector = null)
45  {
46  _data = data;
47  _sortedEnumerator = GetSortedData().GetEnumerator();
48  _keySelector = keySelector ??= baseData => (TKey)(object)baseData.EndTime;
49  }
50 
51  /// <summary>
52  /// Static method to wrap an enumerable with the sort enumerator.
53  /// </summary>
54  /// <param name="preSorted">Indicates if the data is pre-sorted.</param>
55  /// <param name="data">The data to be wrapped into the enumerator.</param>
56  /// <returns>An enumerator over the <see cref="BaseData"/>.</returns>
57  public static IEnumerator<BaseData> TryWrapSortEnumerator(bool preSorted, IEnumerable<BaseData> data)
58  {
59  return preSorted ? new SortEnumerator<TKey>(data) : data.GetEnumerator();
60  }
61 
62  /// <summary>
63  /// Lazily retrieves the sorted data.
64  /// </summary>
65  /// <returns>An enumerable collection of <see cref="BaseData"/>.</returns>
66  private IEnumerable<BaseData> GetSortedData()
67  {
68  foreach (var item in _data.OrderBy(_keySelector))
69  {
70  yield return item;
71  }
72  }
73 
74  object IEnumerator.Current => Current;
75 
76  /// <summary>
77  /// Gets the current <see cref="BaseData"/> element in the collection.
78  /// </summary>
79  public BaseData Current
80  {
81  get => _sortedEnumerator.Current;
82  }
83 
84 
85  /// <summary>
86  /// Advances the enumerator to the next element of the collection.
87  /// </summary>
88  /// <returns>
89  /// <c>true</c> if the enumerator was successfully advanced to the next element;
90  /// <c>false</c> if the enumerator has passed the end of the collection.
91  /// </returns>
92  public bool MoveNext()
93  {
94  return _sortedEnumerator.MoveNext();
95  }
96 
97  /// <summary>
98  /// Resets the enumerator to its initial position, which is before the first element in the collection.
99  /// </summary>
100  public void Reset()
101  {
102  _sortedEnumerator = null;
103  }
104 
105  /// <summary>
106  /// Releases all resources used by the <see cref="SortEnumerator{TKey}"/> and suppresses finalization.
107  /// </summary>
108  public void Dispose()
109  {
110  _sortedEnumerator?.DisposeSafely();
111  }
112  }
113 }