1 #Region "Microsoft.VisualBasic::1d9144da40f5456abf6e070c0204393c, Microsoft.VisualBasic.Core\ComponentModel\Ranges\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 OrderSelector
35     
36     '         Properties: Desc
37     
38     '         Constructor: (+1 OverloadsSub New
39     '         Function: FirstGreaterThan, SelectUntilGreaterThan, SelectUntilLessThan, ToString
40     
41     '     Structure IntTag
42     
43     '         Constructor: (+2 OverloadsSub New
44     '         Function: CompareTo, OrderSelector, ToString
45     
46     
47     ' /********************************************************************************/
48
49 #End Region
50
51 Imports Microsoft.VisualBasic.Serialization.JSON
52 Imports Numeric = Microsoft.VisualBasic.Language.Numeric
53
54 Namespace ComponentModel.Ranges
55
56     Public Class OrderSelector(Of T As IComparable)
57
58         ReadOnly _source As T()
59         ReadOnly _direct As String
60
61         ''' <summary>
62         ''' 是否为降序排序?
63         ''' </summary>
64         ''' <returns></returns>
65         Public ReadOnly Property Desc As Boolean
66
67         Default Public ReadOnly Property value(index%) As T
68             Get
69                 Return _source(index)
70             End Get
71         End Property
72
73         Shared ReadOnly compare As Func(Of T, T) = Function(x) x
74
75         ''' <summary>
76         ''' 
77         ''' </summary>
78         ''' <param name="source"></param>
79         ''' <param name="asc">
80         ''' 当这个参数为真的时候为升序排序
81         ''' </param>
82         Sub New(source As IEnumerable(Of T), Optional asc As Boolean = True)
83             If asc Then
84                 _source = source.OrderBy(compare).ToArray
85                 _direct = " -> "
86             Else
87                 _source = source _
88                     .OrderByDescending(compare) _
89                     .ToArray
90                 _direct = " <- "
91             End If
92
93             Desc = Not asc
94         End Sub
95
96         Public Overrides Function ToString() As String
97             Return $"[{_direct}] {GetType(T).ToString}"
98         End Function
99
100         ''' <summary>
101         ''' 直到当前元素大于指定值
102         ''' </summary>
103         ''' <param name="n"></param>
104         ''' <returns></returns>
105         Public Iterator Function SelectUntilGreaterThan(n As T) As IEnumerable(Of T)
106             For Each x In _source
107                 If Numeric.LessThanOrEquals(x, n) Then
108                     Yield x
109                 Else
110                     Exit For   ' 由于是经过排序了的,所以在这里不再小于的话,则后面的元素都不会再比他小了
111                 End If
112             Next
113         End Function
114
115         ''' <summary>
116         ''' 直到当前元素小于指定值
117         ''' </summary>
118         ''' <param name="n"></param>
119         ''' <returns></returns>
120         Public Iterator Function SelectUntilLessThan(n As T) As IEnumerable(Of T)
121             For Each x In _source
122                 If Numeric.GreaterThanOrEquals(x, n) Then
123                     Yield x
124                 Else
125                     Exit For
126                 End If
127             Next
128         End Function
129
130         ''' <summary>
131         ''' 遍历整个列表直到找到第一个大于<paramref name="o"/>的元素,然后函数会返回这第一个元素的index
132         ''' </summary>
133         ''' <param name="o"></param>
134         ''' <returns>
135         ''' 返回-1表示这个列表之中没有任何元素是大于输入的参数<paramref name="o"/>的
136         ''' </returns>
137         Public Function FirstGreaterThan(o As T) As Integer
138             For i As Integer = 0 To _source.Length - 1
139                 If Not Numeric.GreaterThan(o, _source(i)) Then
140                     Return i
141                 End If
142             Next
143
144             Return -1
145         End Function
146     End Class
147
148     Public Structure IntTag(Of T)
149         Implements IComparable
150
151         Public ReadOnly n As Integer
152         Public ReadOnly x As T
153
154         Sub New(x As T, getInt As Func(Of T, Integer))
155             Me.x = x
156             Me.n = getInt(x)
157         End Sub
158
159         Sub New(n As Integer)
160             Me.n = n
161         End Sub
162
163         Public Overrides Function ToString() As String
164             Return Me.GetJson
165         End Function
166
167         Public Function CompareTo(obj As ObjectAs Integer Implements IComparable.CompareTo
168             If obj Is Nothing Then
169                 Return 1
170             Else
171                 If TypeOf obj Is Integer Then
172                     Return n.CompareTo(DirectCast(obj, Integer))
173                 ElseIf TypeOf obj Is IntTag(Of T) Then
174                     Return n.CompareTo(DirectCast(obj, IntTag(Of T)).n)
175                 Else
176                     Return 0
177                 End If
178             End If
179         End Function
180
181         Public Shared Function OrderSelector(source As IEnumerable(Of T),
182                                              getInt As Func(Of T, Integer),
183                                              Optional asc As Boolean = TrueAs OrderSelector(Of IntTag(Of T))
184             Dim array As IEnumerable(Of IntTag(Of T)) = source.Select(Function(x) New IntTag(Of T)(x, getInt))
185             Dim selects As New OrderSelector(Of IntTag(Of T))(array, asc)
186             Return selects
187         End Function
188
189         Public Shared Widening Operator CType(n As IntegerAs IntTag(Of T)
190             Return New IntTag(Of T)(n)
191         End Operator
192     End Structure
193 End Namespace