2019-03-10 18:10:46 +08:00
|
|
|
|
#Region "Microsoft.VisualBasic::a3729b6eec8989cb5e5f901a6efe3ba6, Microsoft.VisualBasic.Core\Extensions\Collection\Enumerable.vb"
|
|
|
|
|
|
|
2019-03-24 20:39:47 +08:00
|
|
|
|
' 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:
|
|
|
|
|
|
|
|
|
|
|
|
' Module IEnumerations
|
|
|
|
|
|
'
|
|
|
|
|
|
' Function: [Next], CreateDictionary, (+2 Overloads) Differ, (+2 Overloads) FindByItemKey, FindByItemValue
|
|
|
|
|
|
' (+2 Overloads) GetItem, GetItems, Take, (+2 Overloads) Takes, ToDictionary
|
|
|
|
|
|
' ToEntryDictionary
|
|
|
|
|
|
'
|
|
|
|
|
|
' /********************************************************************************/
|
2018-08-02 20:14:48 +08:00
|
|
|
|
|
|
|
|
|
|
#End Region
|
|
|
|
|
|
|
|
|
|
|
|
Imports System.Runtime.CompilerServices
|
|
|
|
|
|
Imports Microsoft.VisualBasic.ComponentModel.Collection
|
|
|
|
|
|
Imports Microsoft.VisualBasic.ComponentModel.Collection.Generic
|
|
|
|
|
|
Imports Microsoft.VisualBasic.Language
|
2019-03-10 18:01:40 +08:00
|
|
|
|
Imports Microsoft.VisualBasic.Language.Default
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Imports Microsoft.VisualBasic.Serialization.JSON
|
|
|
|
|
|
Imports Microsoft.VisualBasic.Text.Xml.Models
|
|
|
|
|
|
Imports Microsoft.VisualBasic.Text.Xml.Models.KeyValuePair
|
|
|
|
|
|
|
|
|
|
|
|
<Extension>
|
|
|
|
|
|
Public Module IEnumerations
|
|
|
|
|
|
|
2019-04-17 23:12:04 +08:00
|
|
|
|
<Extension>
|
|
|
|
|
|
Public Function OfType(Of A, B, T)(source As IEnumerable(Of [Variant](Of A, B))) As IEnumerable(Of T)
|
|
|
|
|
|
Return source.Where(Function(element) element Like GetType(T))
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
2018-12-22 00:33:12 +08:00
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' Get a random element
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="T"></typeparam>
|
|
|
|
|
|
''' <param name="random"></param>
|
|
|
|
|
|
''' <param name="data"></param>
|
|
|
|
|
|
''' <returns></returns>
|
2018-08-02 20:14:48 +08:00
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
|
|
|
|
<Extension>
|
|
|
|
|
|
Public Function [Next](Of T)(random As Random, data As T()) As T
|
|
|
|
|
|
Return data(random.Next(0, data.Length))
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
2019-03-24 20:39:47 +08:00
|
|
|
|
<Extension>
|
|
|
|
|
|
Public Iterator Function ExceptType(Of TIn, T As TIn)(src As IEnumerable(Of TIn)) As IEnumerable(Of TIn)
|
|
|
|
|
|
For Each element As TIn In src
|
|
|
|
|
|
If Not TypeOf element Is T Then
|
|
|
|
|
|
Yield element
|
|
|
|
|
|
End If
|
|
|
|
|
|
Next
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension>
|
|
|
|
|
|
Public Function Differ(Of T As INamedValue, T2)(source As IEnumerable(Of T),
|
|
|
|
|
|
toDiffer As IEnumerable(Of T2),
|
|
|
|
|
|
getId As Func(Of T2, String)) As String()
|
2018-08-02 20:14:48 +08:00
|
|
|
|
|
|
|
|
|
|
Dim targetIndex As String() = (From item As T In source Select item.Key).ToArray
|
|
|
|
|
|
Dim LQuery$() = LinqAPI.Exec(Of String) _
|
|
|
|
|
|
_
|
|
|
|
|
|
() <= From item As T2
|
2019-03-24 20:39:47 +08:00
|
|
|
|
In toDiffer
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Let strId As String = getId(item)
|
|
|
|
|
|
Where Array.IndexOf(targetIndex, strId) = -1
|
|
|
|
|
|
Select strId
|
|
|
|
|
|
|
|
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension> Public Function Differ(Of T As INamedValue, T2 As INamedValue)(source As IEnumerable(Of T), ToDiffer As IEnumerable(Of T2)) As String()
|
|
|
|
|
|
Dim targetIndex As String() = (From item In source Select item.Key).ToArray
|
|
|
|
|
|
Dim LQuery = (From item As T2
|
|
|
|
|
|
In ToDiffer
|
|
|
|
|
|
Where Array.IndexOf(targetIndex, item.Key) = -1
|
|
|
|
|
|
Select item.Key).ToArray
|
|
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension>
|
|
|
|
|
|
Public Function GetItem(Of T As INamedValue)(Id As String, source As IEnumerable(Of T)) As T
|
|
|
|
|
|
Return source.Take(Id)
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension> Public Function GetItems(Of T As INamedValue)(source As IEnumerable(Of T), Id As String) As T()
|
|
|
|
|
|
Dim LQuery = (From ItemObj As T In source Where String.Equals(Id, ItemObj.Key) Select ItemObj).ToArray
|
|
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' 将目标集合对象转换为一个字典对象
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="T"></typeparam>
|
|
|
|
|
|
''' <param name="Collection"></param>
|
|
|
|
|
|
''' <returns></returns>
|
|
|
|
|
|
''' <remarks></remarks>
|
|
|
|
|
|
<Extension> Public Function CreateDictionary(Of T As INamedValue)(Collection As IEnumerable(Of T)) As Dictionary(Of String, T)
|
|
|
|
|
|
Dim Dictionary As New Dictionary(Of String, T)
|
|
|
|
|
|
|
|
|
|
|
|
For Each obj In Collection
|
|
|
|
|
|
Call Dictionary.Add(obj.Key, obj)
|
|
|
|
|
|
Next
|
|
|
|
|
|
|
|
|
|
|
|
Return Dictionary
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
2019-03-10 18:01:40 +08:00
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' Text compare in case sensitive mode
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
ReadOnly TextCompareStrict As DefaultValue(Of StringComparison) = StringComparison.Ordinal
|
|
|
|
|
|
|
|
|
|
|
|
<Extension> Public Function FindByItemKey(source As IEnumerable(Of KeyValuePair), Key As String, Optional strict As Boolean = True) As KeyValuePair()
|
|
|
|
|
|
Dim method As StringComparison = StringComparison.OrdinalIgnoreCase Or TextCompareStrict.When(strict)
|
|
|
|
|
|
Dim LQuery = (From item In source Where String.Equals(item.Key, Key, method) Select item).ToArray
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
2019-03-10 18:01:40 +08:00
|
|
|
|
<Extension> Public Function FindByItemKey(Of PairItemType As IKeyValuePair)(source As IEnumerable(Of PairItemType), Key As String, Optional strict As Boolean = True) As PairItemType()
|
|
|
|
|
|
Dim method As StringComparison = StringComparison.OrdinalIgnoreCase Or TextCompareStrict.When(strict)
|
|
|
|
|
|
Dim LQuery = (From item In source Where String.Equals(item.Key, Key, method) Select item).ToArray
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension> Public Function FindByItemValue(Of PairItemType As IKeyValuePair)(source As IEnumerable(Of PairItemType), Value As String, Optional strict As Boolean = True) As PairItemType()
|
2019-03-10 18:01:40 +08:00
|
|
|
|
Dim method As StringComparison = StringComparison.OrdinalIgnoreCase Or TextCompareStrict.When(strict)
|
|
|
|
|
|
Dim LQuery = (From item In source Where String.Equals(item.Key, Value, method) Select item).ToArray
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' 这个函数假设参数<paramref name="source"/>之中是有重复的对象,则可以使用uniqueID数据提取出一个集合
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="T"></typeparam>
|
|
|
|
|
|
''' <param name="source"></param>
|
|
|
|
|
|
''' <param name="uniqueId"></param>
|
|
|
|
|
|
''' <param name="strict">是否大小写敏感,默认大小写敏感</param>
|
|
|
|
|
|
''' <returns></returns>
|
|
|
|
|
|
<Extension> Public Function Takes(Of T As INamedValue)(source As IEnumerable(Of T), uniqueId As String, Optional strict As Boolean = True) As T()
|
|
|
|
|
|
If source Is Nothing Then
|
|
|
|
|
|
Return New T() {}
|
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
If strict Then
|
|
|
|
|
|
Dim table As Dictionary(Of String, T()) = source _
|
|
|
|
|
|
.GroupBy(Function(o) o.Key) _
|
|
|
|
|
|
.ToDictionary(Function(k) k.Key,
|
|
|
|
|
|
Function(g) g.ToArray)
|
|
|
|
|
|
|
|
|
|
|
|
If table.ContainsKey(uniqueId) Then
|
|
|
|
|
|
Return table(uniqueId)
|
|
|
|
|
|
Else
|
|
|
|
|
|
Return {}
|
|
|
|
|
|
End If
|
|
|
|
|
|
Else
|
|
|
|
|
|
Return LinqAPI.Exec(Of T) _
|
|
|
|
|
|
_
|
|
|
|
|
|
() <= From x As T
|
|
|
|
|
|
In source
|
|
|
|
|
|
Where String.Equals(x.Key, uniqueId, StringComparison.OrdinalIgnoreCase)
|
|
|
|
|
|
Select x
|
|
|
|
|
|
End If
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' 按照uniqueId列表来筛选出目标集合,这个函数是使用字典来进行查询操作的,故而效率会比较高
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="T"></typeparam>
|
|
|
|
|
|
''' <param name="list">The list of ID value for <see cref="INamedValue.Key"/></param>
|
|
|
|
|
|
''' <param name="source"></param>
|
|
|
|
|
|
''' <returns></returns>
|
|
|
|
|
|
''' <remarks></remarks>
|
|
|
|
|
|
<Extension> Public Function Takes(Of T As INamedValue)(list As IEnumerable(Of String), source As IEnumerable(Of T)) As T()
|
|
|
|
|
|
Dim table As Dictionary(Of T) = source.ToDictionary
|
|
|
|
|
|
Dim LQuery As T() = LinqAPI.Exec(Of T) _
|
|
|
|
|
|
_
|
|
|
|
|
|
() <= From sId As String
|
|
|
|
|
|
In list
|
|
|
|
|
|
Where table.ContainsKey(sId)
|
|
|
|
|
|
Select table(sId)
|
|
|
|
|
|
|
|
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' 使用<paramref name="uniqueId"/>唯一标识符从集合之中取出一个目标对象。
|
|
|
|
|
|
''' 小集合推荐使用这个函数,但是对于大型集合或者需要查询的次数非常多的话,则推荐使用字典操作来提升性能
|
|
|
|
|
|
''' 请注意这个函数会完全匹配字符串的,即大小写敏感
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="T"></typeparam>
|
|
|
|
|
|
''' <param name="source"></param>
|
|
|
|
|
|
''' <param name="uniqueId"></param>
|
|
|
|
|
|
''' <returns></returns>
|
|
|
|
|
|
<Extension> Public Function Take(Of T As INamedValue)(source As IEnumerable(Of T), uniqueId As String, Optional strict As Boolean = True) As T
|
2019-03-10 18:01:40 +08:00
|
|
|
|
Dim level As StringComparison = StringComparison.OrdinalIgnoreCase Or TextCompareStrict.When(strict)
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Dim LQuery As T = LinqAPI.DefaultFirst(Of T) _
|
|
|
|
|
|
_
|
|
|
|
|
|
() <= From o As T
|
|
|
|
|
|
In source
|
|
|
|
|
|
Where String.Equals(uniqueId, o.Key, comparisonType:=level)
|
|
|
|
|
|
Select o
|
|
|
|
|
|
|
|
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension> Public Function ToEntryDictionary(Of T As IReadOnlyId)(source As IEnumerable(Of T)) As Dictionary(Of String, T)
|
|
|
|
|
|
Return source.ToDictionary(Function(item As T) item.Identity)
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
<Extension> Public Function GetItem(Of T As IReadOnlyId)(source As IEnumerable(Of T), uniqueId As String, Optional caseSensitive As Boolean = True) As T
|
2019-03-10 18:01:40 +08:00
|
|
|
|
Dim method As StringComparison = StringComparison.OrdinalIgnoreCase Or TextCompareStrict.When(caseSensitive)
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Dim LQuery = LinqAPI.DefaultFirst(Of T) _
|
|
|
|
|
|
_
|
|
|
|
|
|
() <= From itemObj As T
|
|
|
|
|
|
In source
|
|
|
|
|
|
Where String.Equals(itemObj.Identity, uniqueId, method)
|
|
|
|
|
|
Select itemObj
|
|
|
|
|
|
|
|
|
|
|
|
Return LQuery
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
|
|
|
|
'''
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="T"></typeparam>
|
|
|
|
|
|
''' <param name="source"></param>
|
|
|
|
|
|
''' <param name="distinct">
|
|
|
|
|
|
''' True: 这个参数会去处重复项
|
|
|
|
|
|
''' </param>
|
|
|
|
|
|
''' <returns></returns>
|
|
|
|
|
|
<Extension> Public Function ToDictionary(Of T As INamedValue)(source As IEnumerable(Of T), distinct As Boolean) As Dictionary(Of T)
|
|
|
|
|
|
If Not distinct Then
|
|
|
|
|
|
Return source.ToDictionary
|
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
Dim table As New Dictionary(Of T)
|
|
|
|
|
|
Dim duplicates As New List(Of String)
|
|
|
|
|
|
|
|
|
|
|
|
For Each x As T In source
|
|
|
|
|
|
If Not table.ContainsKey(x.Key) Then
|
|
|
|
|
|
Call table.Add(x.Key, x)
|
|
|
|
|
|
Else
|
|
|
|
|
|
duplicates += x.Key
|
|
|
|
|
|
End If
|
|
|
|
|
|
Next
|
|
|
|
|
|
|
2019-04-08 19:41:19 +08:00
|
|
|
|
If duplicates > 0 Then
|
2018-08-02 20:14:48 +08:00
|
|
|
|
Call $"Dictionary table build complete, but there is dulplicated keys: {duplicates.GetJson}...".Warning
|
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
Return table
|
|
|
|
|
|
End Function
|
|
|
|
|
|
End Module
|