microsoft-visualbasic-runtime/ComponentModel/System.Collections.Generic/IndexOf.vb

391 lines
14 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::d20bb5be4046a2734ca54f784bfe4ae8, Microsoft.VisualBasic.Core\ComponentModel\System.Collections.Generic\IndexOf.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Class Index
'
' Properties: Count, Map, Objects
'
' Constructor: (+4 Overloads) Sub New
'
' Function: Add, EnumerateMapKeys, GetEnumerator, GetOrdinal, IEnumerable_GetEnumerator
' indexing, (+2 Overloads) Intersect, NotExists, ToString
'
' Sub: Clear, Delete
'
' Operators: -, (+2 Overloads) +, <>, =, (+2 Overloads) IsFalse
' (+2 Overloads) IsTrue, (+2 Overloads) Like
'
'
' /********************************************************************************/
#End Region
Imports System.Runtime.CompilerServices
Imports Microsoft.VisualBasic.Language
Imports Microsoft.VisualBasic.Language.Default
Imports Microsoft.VisualBasic.Linq
Imports Microsoft.VisualBasic.Serialization.JSON
Namespace ComponentModel.Collection
''' <summary>
''' Mappings of ``key As String -> index As Integer``
''' </summary>
''' <typeparam name="T"></typeparam>
''' <remarks>
''' ###### 2017-12-10
'''
''' 经过测试字典对象是完全可以容纳UniProt数据库之中的物种的数量上限的
''' </remarks>
Public Class Index(Of T) : Implements IEnumerable(Of SeqValue(Of T))
Dim maps As New Dictionary(Of T, Integer)
Dim index As HashList(Of SeqValue(Of T))
Dim base%
''' <summary>
''' 获取包含在<see cref="System.Collections.Generic.Dictionary"/>中的键/值对的数目。
''' </summary>
''' <returns></returns>
Public ReadOnly Property Count As Integer
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Get
Return maps.Count
End Get
End Property
''' <summary>
''' Gets the input object keys that using for the construction of this index.
''' </summary>
''' <returns></returns>
Public ReadOnly Property Objects As T()
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Get
Return maps.Keys.ToArray
End Get
End Property
''' <summary>
''' 请注意这里的数据源请尽量使用Distinct的否则对于重复的数据只会记录下第一个位置
''' </summary>
''' <param name="source"></param>
Sub New(source As IEnumerable(Of T), Optional base% = 0)
If source Is Nothing Then
source = {}
End If
For Each x As SeqValue(Of T) In source.SeqIterator
If Not maps.ContainsKey(x) Then
Call maps.Add(+x, x.i + base)
End If
Next
Me.base = base
Me.index = indexing()
End Sub
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Private Function indexing() As HashList(Of SeqValue(Of T))
Return maps _
.Select(Function(s)
Return New SeqValue(Of T) With {
.i = s.Value,
.value = s.Key
}
End Function) _
.AsHashList
End Function
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Sub New(ParamArray vector As T())
Call Me.New(source:=DirectCast(vector, IEnumerable(Of T)))
End Sub
''' <summary>
''' 默认是从0开始的
''' </summary>
''' <param name="base"></param>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Sub New(base As Integer)
Call Me.New({}, base:=base)
End Sub
''' <summary>
'''
''' </summary>
''' <param name="maps">如果是json加载可能会出现空值的字典</param>
''' <param name="base%"></param>
Sub New(maps As IDictionary(Of T, Integer), Optional base% = 0)
Static emptyIndex As [Default](Of IDictionary(Of String, Integer)) =
New Dictionary(Of String, Integer)
Me.base = base
Me.maps = New Dictionary(Of T, Integer)(dictionary:=maps Or emptyIndex)
Me.index = indexing()
End Sub
''' <summary>
''' 获取目标对象在本索引之中的位置编号,不存在则返回-1
''' </summary>
''' <param name="x"></param>
''' <returns></returns>
Default Public ReadOnly Property IndexOf(x As T) As Integer
Get
If maps.ContainsKey(x) Then
Return maps(x)
Else
Return -1
End If
End Get
End Property
''' <summary>
''' 直接通过索引获取目标对象的值,请注意,如果<typeparamref name="T"/>泛型类型是<see cref="Integer"/>
''' 则如果需要查找index的话则必须要显式的指定参数名为``x:=``,否则调用的是当前的这个索引方法,
''' 得到错误的结果
''' </summary>
''' <param name="index%"></param>
''' <returns></returns>
Default Public ReadOnly Property IndexOf(index As Integer) As T
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Get
Return Me.index(index).value
End Get
End Property
''' <summary>
''' 与<see cref="Objects"/>只读属性的功能相似只不过这个函数是Linq枚举器模式
''' </summary>
''' <returns></returns>
Public Function EnumerateMapKeys() As IEnumerable(Of String)
Return maps.Keys.AsEnumerable
End Function
Public Function GetOrdinal(items As IEnumerable(Of T)) As Integer()
Return items.Select(Function(element) Me(element)).ToArray
End Function
Public Sub Delete(index As T)
Dim i = Me.IndexOf(index)
If i > -1 Then
Me.maps.Remove(index)
Me.index(i) = Nothing
End If
End Sub
Public Iterator Function Intersect(collection As IEnumerable(Of T)) As IEnumerable(Of T)
For Each x As T In collection
If IndexOf(x) > -1 Then
Yield x
End If
Next
End Function
Public Iterator Function Intersect(compares As Index(Of T)) As IEnumerable(Of T)
For Each x As T In compares.maps.Keys
If IndexOf(x) > -1 Then
Yield x
End If
Next
End Function
''' <summary>
''' For Linq ``where``
''' </summary>
''' <param name="x"></param>
''' <returns></returns>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function NotExists(x As T) As Boolean
Return IndexOf(x) = -1
End Function
''' <summary>
''' 这个函数是线程不安全的
''' </summary>
''' <param name="x"></param>
''' <returns>
''' 这个函数所返回来的值是所添加的<paramref name="x"/>的index值
''' </returns>
Public Function Add(x As T) As Integer
If Not maps.ContainsKey(x) Then
Call maps.Add(x, maps.Count + base)
Call index.Add(
x:=New SeqValue(Of T) With {
.i = maps(x),
.value = x
})
End If
Return maps(x)
End Function
Public Sub Clear()
Call maps.Clear()
Call index.Clear()
End Sub
''' <summary>
''' Display the input source sequence.
''' </summary>
''' <returns></returns>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Overrides Function ToString() As String
Return maps.Keys _
.Select(Function(x) x.ToString) _
.ToArray _
.GetJson
End Function
''' <summary>
''' Returns the ``obj => index`` mapping table.
''' </summary>
''' <returns></returns>
Public ReadOnly Property Map As Dictionary(Of T, Integer)
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Get
Return Me
End Get
End Property
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Narrowing Operator CType(index As Index(Of T)) As Dictionary(Of T, Integer)
Return New Dictionary(Of T, Integer)(index.maps)
End Operator
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Widening Operator CType(objs As T()) As Index(Of T)
Return New Index(Of T)(source:=objs)
End Operator
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Widening Operator CType(list As List(Of T)) As Index(Of T)
Return New Index(Of T)(source:=list)
End Operator
''' <summary>
''' Add a new key to this index object.
''' </summary>
''' <param name="index">Element key index object.</param>
''' <param name="element"></param>
''' <returns></returns>
Public Shared Operator +(index As Index(Of T), element As T) As Index(Of T)
Call index.Add(element)
Return index
End Operator
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Operator +(list As List(Of T), index As Index(Of T)) As List(Of T)
Return list + index.Objects
End Operator
''' <summary>
''' Delete items from source <paramref name="index"/> and then returns the new modify index collection
''' </summary>
''' <param name="index"></param>
''' <param name="list"></param>
''' <returns></returns>
Public Shared Operator -(index As Index(Of T), list As List(Of T)) As Index(Of T)
Dim table = index.maps
For Each item As T In list
If table.ContainsKey(item) Then
Call table.Remove(item)
End If
Next
Return New Index(Of T)(table.Keys)
End Operator
''' <summary>
''' <paramref name="item"/> is one of the element in <paramref name="indexr"/>
''' </summary>
''' <param name="item"></param>
''' <param name="indexr"></param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Operator Like(item As T, indexr As Index(Of T)) As Boolean
If item Is Nothing OrElse indexr Is Nothing Then
Return False
Else
Return indexr(x:=item) > -1
End If
End Operator
Public Iterator Function GetEnumerator() As IEnumerator(Of SeqValue(Of T)) Implements IEnumerable(Of SeqValue(Of T)).GetEnumerator
For Each o As SeqValue(Of T) In index
Yield o
Next
End Function
Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Yield GetEnumerator()
End Function
''' <summary>
''' The element numbers in current index object is equals to given count number value?
''' </summary>
''' <param name="index"></param>
''' <param name="count%"></param>
''' <returns></returns>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Operator =(index As Index(Of T), count%) As Boolean
Return index.Count = count
End Operator
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Operator <>(index As Index(Of T), count%) As Boolean
Return Not index = count
End Operator
Public Shared Operator IsTrue(index As Index(Of T)) As Boolean
If index Is Nothing Then
Return False
ElseIf index.Count = 0 Then
Return False
ElseIf index.Count = 1 AndAlso Len(CObj(index.Objects(Scan0))) = 0 Then
Return False
Else
Return True
End If
End Operator
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Operator IsFalse(index As Index(Of T)) As Boolean
Return Not op_True(index)
End Operator
End Class
End Namespace