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