1 #Region "Microsoft.VisualBasic::ced01ef1b9c96a858cbd3d0a6c87f4bd, Microsoft.VisualBasic.Core\ComponentModel\System.Collections.Generic\IndexOf.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 Index
35
36 '         Properties: Count, Map, Objects
37
38 '         Constructor: (+2 OverloadsSub New
39
40 '         FunctionGetEnumerator, IEnumerable_GetEnumerator, (+2 OverloadsIntersect, NotExists, ToString
41
42 '         Sub: Add, Clear
43
44
45 ' /********************************************************************************/
46
47 #End Region
48
49 Imports System.Runtime.CompilerServices
50 Imports Microsoft.VisualBasic.Linq
51 Imports Microsoft.VisualBasic.Serialization.JSON
52
53 Namespace ComponentModel.Collection
54
55     ''' <summary>
56     ''' Mappings of ``key As String -> index As Integer``
57     ''' </summary>
58     ''' <typeparam name="T"></typeparam>
59     ''' <remarks>
60     ''' ###### 2017-12-10
61     ''' 
62     ''' 经过测试,字典对象是完全可以容纳UniProt数据库之中的物种的数量上限的
63     ''' </remarks>
64     Public Class Index(Of T) : Implements IEnumerable(Of SeqValue(Of T))
65
66         Dim maps As New Dictionary(Of T, Integer)
67         Dim index As HashList(Of SeqValue(Of T))
68         Dim base%
69
70         ''' <summary>
71         ''' 获取包含在<see cref="System.Collections.Generic.Dictionary"/>中的键/值对的数目。
72         ''' </summary>
73         ''' <returns></returns>
74         Public ReadOnly Property Count As Integer
75             <MethodImpl(MethodImplOptions.AggressiveInlining)>
76             Get
77                 Return maps.Count
78             End Get
79         End Property
80
81         ''' <summary>
82         ''' Gets the input object keys that using for the construction of this index.
83         ''' </summary>
84         ''' <returns></returns>
85         Public ReadOnly Property ObjectAs T()
86             <MethodImpl(MethodImplOptions.AggressiveInlining)>
87             Get
88                 Return maps.Keys.ToArray
89             End Get
90         End Property
91
92         ''' <summary>
93         ''' 请注意,这里的数据源请尽量使用Distinct的,否则对于重复的数据,只会记录下第一个位置
94         ''' </summary>
95         ''' <param name="source"></param>
96         Sub New(source As IEnumerable(Of T), Optional base% = 0)
97             If source Is Nothing Then
98                 source = {}
99             End If
100
101             For Each x As SeqValue(Of T) In source.SeqIterator
102                 If Not maps.ContainsKey(x) Then
103                     Call maps.Add(+x, x.i + base)
104                 End If
105             Next
106
107             Me.base = base
108             Me.index = maps _
109                 .Select(Function(s)
110                             Return New SeqValue(Of T) With {
111                                 .i = s.Value,
112                                 .value = s.Key
113                             }
114                         End Function) _
115                 .AsHashList
116         End Sub
117
118         <MethodImpl(MethodImplOptions.AggressiveInlining)>
119         Sub New(ParamArray vector As T())
120             Call Me.New(source:=DirectCast(vector, IEnumerable(Of T)))
121         End Sub
122
123         ''' <summary>
124         ''' 默认是从0开始的
125         ''' </summary>
126         ''' <param name="base"></param>
127         Sub New(base As Integer)
128             Call Me.New({}, base:=base)
129         End Sub
130
131         ''' <summary>
132         ''' 获取目标对象在本索引之中的位置编号,不存在则返回-1
133         ''' </summary>
134         ''' <param name="x"></param>
135         ''' <returns></returns>
136         Default Public ReadOnly Property IndexOf(x As T) As Integer
137             Get
138                 If maps.ContainsKey(x) Then
139                     Return maps(x)
140                 Else
141                     Return -1
142                 End If
143             End Get
144         End Property
145
146         ''' <summary>
147         ''' 直接通过索引获取目标对象的值,请注意,如果<typeparamref name="T"/>泛型类型是<see cref="Integer"/>,
148         ''' 则如果需要查找index的话,则必须要显式的指定参数名为``x:=``,否则调用的是当前的这个索引方法,
149         ''' 得到错误的结果
150         ''' </summary>
151         ''' <param name="index%"></param>
152         ''' <returns></returns>
153         Default Public ReadOnly Property IndexOf(index%) As T
154             <MethodImpl(MethodImplOptions.AggressiveInlining)>
155             Get
156                 Return Me.index(index).value
157             End Get
158         End Property
159
160         Public Iterator Function Intersect(collection As IEnumerable(Of T)) As IEnumerable(Of T)
161             For Each x As T In collection
162                 If IndexOf(x) > -1 Then
163                     Yield x
164                 End If
165             Next
166         End Function
167
168         Public Iterator Function Intersect(compares As Index(Of T)) As IEnumerable(Of T)
169             For Each x As T In compares.maps.Keys
170                 If IndexOf(x) > -1 Then
171                     Yield x
172                 End If
173             Next
174         End Function
175
176         ''' <summary>
177         ''' For Linq ``where``
178         ''' </summary>
179         ''' <param name="x"></param>
180         ''' <returns></returns>
181         <MethodImpl(MethodImplOptions.AggressiveInlining)>
182         Public Function NotExists(x As T) As Boolean
183             Return IndexOf(x) = -1
184         End Function
185
186         ''' <summary>
187         ''' 这个函数是线程不安全的
188         ''' </summary>
189         ''' <param name="x"></param>
190         ''' <returns>
191         ''' 这个函数所返回来的值是所添加的<paramref name="x"/>的index值
192         ''' </returns>
193         Public Function Add(x As T) As Integer
194             If Not maps.ContainsKey(x) Then
195                 Call maps.Add(x, maps.Count + base)
196                 Call index.Add(
197                     x:=New SeqValue(Of T) With {
198                         .i = maps(x),
199                         .value = x
200                     })
201             End If
202
203             Return maps(x)
204         End Function
205
206         Public Sub Clear()
207             Call maps.Clear()
208             Call index.Clear()
209         End Sub
210
211         ''' <summary>
212         ''' Display the input source sequence.
213         ''' </summary>
214         ''' <returns></returns>
215         <MethodImpl(MethodImplOptions.AggressiveInlining)>
216         Public Overrides Function ToString() As String
217             Return maps.Keys _
218                 .Select(Function(x) x.ToString) _
219                 .ToArray _
220                 .GetJson
221         End Function
222
223         Public ReadOnly Property Map As Dictionary(Of T, Integer)
224             <MethodImpl(MethodImplOptions.AggressiveInlining)>
225             Get
226                 Return Me
227             End Get
228         End Property
229
230         <MethodImpl(MethodImplOptions.AggressiveInlining)>
231         Public Shared Narrowing Operator CType(index As Index(Of T)) As Dictionary(Of T, Integer)
232             Return New Dictionary(Of T, Integer)(index.maps)
233         End Operator
234
235         <MethodImpl(MethodImplOptions.AggressiveInlining)>
236         Public Shared Widening Operator CType(objs As T()) As Index(Of T)
237             Return New Index(Of T)(source:=objs)
238         End Operator
239
240         Public Shared Operator +(index As Index(Of T), element As T) As Index(Of T)
241             Call index.Add(element)
242             Return index
243         End Operator
244
245         Public Iterator Function GetEnumerator() As IEnumerator(Of SeqValue(Of T)) Implements IEnumerable(Of SeqValue(Of T)).GetEnumerator
246             For Each o As SeqValue(Of T) In index
247                 Yield o
248             Next
249         End Function
250
251         Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
252             Yield GetEnumerator()
253         End Function
254     End Class
255 End Namespace