1 #Region "Microsoft.VisualBasic::b7b6985a0997ef3768ef740897ce76e6, Microsoft.VisualBasic.Core\ComponentModel\Ranges\Selector\IndexSelector.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Class IndexSelector
35     
36     '         Constructor: (+2 OverloadsSub New
37     '         Function: FromSortSequence, SelectByRange
38     
39     '     Class OrderSelector
40     
41     '         Properties: Count, Desc
42     
43     '         Constructor: (+1 OverloadsSub New
44     '         Function: Find, FirstGreaterThan, GetEnumerator, IEnumerable_GetEnumerator, SelectByRange
45     '                   SelectUntilGreaterThan, SelectUntilLessThan, ToString
46     
47     
48     ' /********************************************************************************/
49
50 #End Region
51
52 Imports System.Runtime.CompilerServices
53 Imports Microsoft.VisualBasic.ComponentModel.TagData
54 Imports Numeric = Microsoft.VisualBasic.Language.Numeric
55
56 Namespace ComponentModel.Ranges
57
58     ''' <summary>
59     ''' A numeric index helper
60     ''' </summary>
61     Public Class IndexSelector : Inherits OrderSelector(Of NumericTagged(Of Integer))
62
63         <MethodImpl(MethodImplOptions.AggressiveInlining)>
64         Public Sub New(source As IEnumerable(Of Double), Optional asc As Boolean = True)
65             MyBase.New(source.Select(Function(d, i) New NumericTagged(Of Integer)(d, i)), asc)
66         End Sub
67
68         Private Sub New(sorts As IEnumerable(Of NumericTagged(Of Integer)), asc As Boolean)
69             Call MyBase.New({}, asc)
70             source = sorts.ToArray
71         End Sub
72
73         ''' <summary>
74         ''' Get index by a given numeric range
75         ''' </summary>
76         ''' <param name="min"></param>
77         ''' <param name="max"></param>
78         ''' <returns></returns>
79         Public Overloads Function SelectByRange(min As Double, max As DoubleAs IEnumerable(Of Integer)
80             Dim minValue As New NumericTagged(Of Integer)(min, 0)
81             Dim maxvalue As New NumericTagged(Of Integer)(max, 0)
82
83             Return source.SkipWhile(Function(o) Numeric.LessThan(o, minValue)) _
84                          .TakeWhile(Function(o) Numeric.LessThanOrEquals(o, maxvalue)) _
85                          .Select(Function(tag)
86                                      Return tag.value
87                                  End Function)
88         End Function
89
90         ''' <summary>
91         ''' 所使用的序列参数必须是经过了排序操作的
92         ''' </summary>
93         ''' <param name="seq"></param>
94         ''' <returns></returns>
95         <MethodImpl(MethodImplOptions.AggressiveInlining)>
96         Public Shared Function FromSortSequence(seq As Double()) As IndexSelector
97             Return New IndexSelector(seq.Select(Function(d, i) New NumericTagged(Of Integer)(d, i)), True)
98         End Function
99     End Class
100
101     Public Class OrderSelector(Of T As IComparable) : Implements IReadOnlyCollection(Of T)
102
103         ''' <summary>
104         ''' <see cref="source"/>序列的排序的方向字符串显示
105         ''' </summary>
106         ReadOnly direct As String
107
108         ''' <summary>
109         ''' 目标序列
110         ''' </summary>
111         Protected source As T()
112
113         ''' <summary>
114         ''' 是否为降序排序?
115         ''' </summary>
116         ''' <returns></returns>
117         Public ReadOnly Property Desc As Boolean
118
119         Default Public ReadOnly Property Item(index%) As T
120             <MethodImpl(MethodImplOptions.AggressiveInlining)>
121             Get
122                 Return source(index)
123             End Get
124         End Property
125
126         Public ReadOnly Property Count As Integer Implements IReadOnlyCollection(Of T).Count
127             <MethodImpl(MethodImplOptions.AggressiveInlining)>
128             Get
129                 Return source.Length
130             End Get
131         End Property
132
133         Shared ReadOnly compare As Func(Of T, T) = Function(x) x
134
135         ''' <summary>
136         ''' 
137         ''' </summary>
138         ''' <param name="source"></param>
139         ''' <param name="asc">
140         ''' 当这个参数为真的时候为升序排序
141         ''' </param>
142         Sub New(source As IEnumerable(Of T), Optional asc As Boolean = True)
143             If asc Then
144                 Me.source = source.OrderBy(compare).ToArray
145                 direct = " -> "
146             Else
147                 Me.source = source _
148                     .OrderByDescending(compare) _
149                     .ToArray
150                 direct = " <- "
151             End If
152
153             Desc = Not asc
154         End Sub
155
156         ''' <summary>
157         ''' Find value by key via binary search
158         ''' </summary>
159         ''' <typeparam name="K"></typeparam>
160         ''' <param name="key"></param>
161         ''' <returns></returns>
162         ''' 
163         <MethodImpl(MethodImplOptions.AggressiveInlining)>
164         Public Function Find(Of K As IComparable(Of K))(key As K, getKey As Func(Of T, K), Optional [default] As T = NothingAs T
165             Return source.BinarySearch(key, getKey, [default])
166         End Function
167
168         <MethodImpl(MethodImplOptions.AggressiveInlining)>
169         Public Overrides Function ToString() As String
170             Return $"[{direct}] {GetType(T).ToString}"
171         End Function
172
173         ''' <summary>
174         ''' 直到当前元素大于指定值
175         ''' </summary>
176         ''' <param name="n"></param>
177         ''' <returns></returns>
178         Public Iterator Function SelectUntilGreaterThan(n As T) As IEnumerable(Of T)
179             For Each x In source
180                 If Numeric.LessThanOrEquals(x, n) Then
181                     Yield x
182                 Else
183                     ' 由于是经过排序了的,所以在这里不再小于的话,则后面的元素都不会再比他小了
184                     Exit For
185                 End If
186             Next
187         End Function
188
189         ''' <summary>
190         ''' 直到当前元素小于指定值
191         ''' </summary>
192         ''' <param name="n"></param>
193         ''' <returns></returns>
194         Public Iterator Function SelectUntilLessThan(n As T) As IEnumerable(Of T)
195             For Each x In source
196                 If Numeric.GreaterThanOrEquals(x, n) Then
197                     Yield x
198                 Else
199                     Exit For
200                 End If
201             Next
202         End Function
203
204         ''' <summary>
205         ''' 遍历整个列表直到找到第一个大于<paramref name="o"/>的元素,然后函数会返回这第一个元素的index
206         ''' </summary>
207         ''' <param name="o"></param>
208         ''' <returns>
209         ''' 返回-1表示这个列表之中没有任何元素是大于输入的参数<paramref name="o"/>的
210         ''' </returns>
211         Public Function FirstGreaterThan(o As T) As Integer
212             For i As Integer = 0 To source.Length - 1
213                 If Not Numeric.GreaterThan(o, source(i)) Then
214                     Return i
215                 End If
216             Next
217
218             Return -1
219         End Function
220
221         <MethodImpl(MethodImplOptions.AggressiveInlining)>
222         Public Function SelectByRange(min As T, max As T) As IEnumerable(Of T)
223             Return source.SkipWhile(Function(o) Numeric.LessThan(o, min)) _
224                          .TakeWhile(Function(o) Numeric.LessThanOrEquals(o, max))
225         End Function
226
227         Public Iterator Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
228             For Each x As T In source
229                 Yield x
230             Next
231         End Function
232
233         Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
234             Yield GetEnumerator()
235         End Function
236     End Class
237 End Namespace