microsoft-visualbasic-runtime/Extensions/Collection/Linq/Takes.vb

192 lines
7.4 KiB
VB.net
Raw Normal View History

2019-11-10 15:16:27 +08:00
#Region "Microsoft.VisualBasic::c2368b41d83cc9e285798beca0da0501, Microsoft.VisualBasic.Core\Extensions\Collection\Linq\Takes.vb"
2019-06-15 17:34:52 +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 TakesExtension
'
2019-06-28 23:45:04 +08:00
' Function: doReversedTake, (+2 Overloads) TakeRandomly, (+3 Overloads) Takes
2019-06-15 17:34:52 +08:00
'
'
' /********************************************************************************/
#End Region
Imports System.Runtime.CompilerServices
2019-06-04 20:43:55 +08:00
Imports Microsoft.VisualBasic.CommandLine.Reflection
Imports Microsoft.VisualBasic.ComponentModel.Collection
Imports Microsoft.VisualBasic.Language
2019-06-21 22:15:57 +08:00
Imports Microsoft.VisualBasic.Math
2019-06-04 20:43:55 +08:00
Namespace Linq
Public Module TakesExtension
''' <summary>
''' An wrapper of <see cref="Array.ConstrainedCopy"/>
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="source"></param>
''' <param name="count"></param>
''' <returns></returns>
<Extension>
Public Function Takes(Of T)(source As T(), count As Integer) As T()
Dim bufs As T() = New T(count - 1) {}
Call Array.ConstrainedCopy(source, Scan0, bufs, Scan0, count)
Return bufs
End Function
''' <summary>
''' 将所有对应的index处的<paramref name="flags"/>值为True的元素返回
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="source"></param>
''' <param name="flags"></param>
''' <returns></returns>
2019-10-12 22:38:14 +08:00
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
2019-06-04 20:43:55 +08:00
<Extension>
2019-10-12 22:38:14 +08:00
Public Function Takes(Of T)(source As IEnumerable(Of T), flags As Boolean()) As IEnumerable(Of T)
Return source.Where(Function(obj, i) flags(i))
2019-06-04 20:43:55 +08:00
End Function
''' <summary>
''' Take elements by <paramref name="index"/> list.
''' (将指定<paramref name="index"/>下标的元素从原始数据<paramref name="source"/>序列之中提取出来)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="source"></param>
''' <param name="index">所要获取的目标对象的下表的集合</param>
''' <param name="reversed">是否为反向选择即返回所有不在目标index集合之中的元素列表</param>
''' <param name="OffSet">当进行反选的时候,本参数将不会起作用</param>
''' <returns></returns>
''' <remarks>
''' ###### 2018-3-30 函数经过测试没有问题
''' </remarks>
<ExportAPI("takes")>
<Extension>
Public Function Takes(Of T)(source As IEnumerable(Of T),
index%(),
Optional offSet% = 0,
Optional reversed As Boolean = False) As T()
If reversed Then
2019-06-21 22:15:57 +08:00
Return source.doReversedTake(index).ToArray
2019-06-04 20:43:55 +08:00
End If
Dim result As T() = New T(index.Length - 1) {}
Dim indices As Index(Of Integer) = index _
.Select(Function(oi) oi + offSet) _
.Indexing
For Each x As SeqValue(Of T) In source.SeqIterator
' 在这里得到的是x的index在indexs参数之中的索引位置
Dim i% = indices.IndexOf(x:=x.i)
' 当前的原始的下表位于indexs参数值中则第i个indexs元素所指向的source的元素
' 就是x 将其放入对应的结果列表之中
If i > -1 Then
result(i) = x.value
End If
Next
Return result
End Function
''' <summary>
''' 反选,即将所有不出现在<paramref name="index"></paramref>之中的元素都选取出来
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="collection"></param>
''' <param name="index"></param>
''' <returns></returns>
''' <remarks></remarks>
'''
<Extension>
2019-06-21 22:15:57 +08:00
Private Iterator Function doReversedTake(Of T)(collection As IEnumerable(Of T), index As Integer()) As IEnumerable(Of T)
2019-06-04 20:43:55 +08:00
Dim indices As New Index(Of Integer)(index)
For Each x As SeqValue(Of T) In collection.SeqIterator
' 不存在于顶点的列表之中,即符合反选的条件,则添加进入结果之中
If indices.IndexOf(x:=x.i) = -1 Then
Yield x.value
End If
Next
End Function
2019-06-21 22:15:57 +08:00
''' <summary>
''' 随机的在目标集合中选取指定数目的子集合
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="source"></param>
''' <param name="counts">当目标数目大于或者等于目标集合的数目的时候,则返回目标集合</param>
''' <returns></returns>
''' <remarks></remarks>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension>
Public Function TakeRandomly(Of T)(source As IEnumerable(Of T), counts%) As T()
Return source.SafeQuery _
.ToArray _
.TakeRandomly(counts) _
.ToArray
End Function
''' <summary>
''' 随机的在目标集合中选取指定数目的子集合
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="array"></param>
''' <param name="counts">当目标数目大于或者等于目标集合的数目的时候,则返回目标集合</param>
''' <returns></returns>
''' <remarks></remarks>
<Extension>
Public Function TakeRandomly(Of T)(array As T(), counts%) As IEnumerable(Of T)
If counts >= array.Length Then
Dim out As T() = New T(array.Length - 1) {}
Call System.Array.ConstrainedCopy(array, Scan0, out, Scan0, array.Length)
Return out
Else
Dim out As T() = New T(counts - 1) {}
Dim input As New List(Of T)(array)
Dim ind As Integer
For i As Integer = 0 To counts - 1
ind = seeds.Next(input.Count)
out(i) = input(ind)
input.RemoveAt(ind)
Next
Return out
End If
End Function
2019-06-04 20:43:55 +08:00
End Module
2019-06-15 17:34:52 +08:00
End Namespace