1 #Region "Microsoft.VisualBasic::e542c326192d9958ec289a8f4051e6bc, Microsoft.VisualBasic.Core\ComponentModel\DataStructures\Set\SetAPI.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 GenericLambda
35     
36     
37     '     Delegate Function
38     
39     
40     '     Delegate Function
41     
42     
43     
44     Module SetAPI
45     
46     '     Function: Contains, (+3 OverloadsIntersection
47     '     Structure __stringCompares
48     
49     '         Constructor: (+1 OverloadsSub New
50     '         Function: Equals
51     
52     
53     
54     
55     
56     
57     
58     ' /********************************************************************************/
59
60 #End Region
61
62 Imports System.Runtime.CompilerServices
63 Imports Microsoft.VisualBasic.Linq
64 Imports Microsoft.VisualBasic.Language
65
66 Public NotInheritable Class GenericLambda(Of T)
67
68     Public Delegate Function IEquals(a As T, b As T) As Boolean
69     Public Delegate Function GetUid(x As T) As String
70
71 End Class
72
73 Public Module SetAPI
74
75     '''<summary>
76     ''' Performs an intersection of two sets.(求交集,这个函数总是会挑选出<paramref name="s1"/>集合之中的元素的)
77     ''' </summary>
78     ''' <param name="s1">Any set.</param>
79     ''' <param name="s2">Any set.</param>
80     ''' <returns>A new <see cref="[Set]">Set</see> object that contains the members
81     ''' that were common to both of the input sets.</returns>
82     <Extension>
83     Public Function Intersection(Of T)(s1 As IEnumerable(Of T), s2 As IEnumerable(Of T), getUID As GenericLambda(Of T).GetUid) As T()
84         Dim tags = (From x As T In s1 Let uid As String = getUID(x) Select uid, tag = NameOf(s1), x).AsList +
85             From x As T
86             In s2
87             Let uid As String = getUID(x)
88             Select uid,
89                 tag = NameOf(s2),
90                 x
91         Dim intersectGroups = From g
92                               In tags.GroupBy(Function(x) x.uid) ' 按照uid字符串进行分组
93                               Let source = g.ToArray
94                               Let taglist As String() = source _
95                                    .Select(Function(x) x.tag) _
96                                    .Distinct _
97                                    .ToArray
98                               Where taglist.Length > 1 ' 对每一个分组数据,根据标签的数量来了解是否为交集的一部分,当为交集元素的时候,标签的数量是两个,即同时存在于两个集合之众
99                               Select source
100         ' 总是挑选出s1的数据
101         Dim result = LinqAPI.Exec(Of T) _
102  _
103             () <= From x
104                   In intersectGroups
105                   Let s1Group = x.Where(Function(o) o.tag = NameOf(s1)).First
106                   Let value As T = s1Group.x
107                   Select value
108
109         Return result
110     End Function
111
112     '''<summary>
113     ''' Performs an intersection of two sets.(求交集)
114     ''' </summary>
115     ''' <param name="s1">Any set.</param>
116     ''' <param name="s2">Any set.</param>
117     ''' <returns>A new <see cref="[Set]">Set</see> object that contains the members
118     ''' that were common to both of the input sets.</returns>
119     ''' 
120     <Extension>
121     Public Function Intersection(Of T)(s1 As IEnumerable(Of T), s2 As IEnumerable(Of T), __equals As GenericLambda(Of T).IEquals) As T()
122         Dim result As New List(Of T)
123
124         If s1.Count > s2.Count Then
125             For Each o As T In s1
126                 If s2.Contains(o, __equals) Then
127                     result.Add(o)
128                 End If
129             Next
130         Else
131             For Each o As T In s2
132                 If s1.Contains(o, __equals) Then
133                     result.Add(o)
134                 End If
135             Next
136         End If
137
138         Return result
139     End Function
140
141     <Extension>
142     Public Function Contains(Of T)([set] As IEnumerable(Of T), x As T, __equals As GenericLambda(Of T).IEquals) As Boolean
143         Dim LQuery = (From obj As T In [set].AsParallel Where __equals(x, obj) Select 1).FirstOrDefault
144         Return LQuery > 0
145     End Function
146
147     <Extension>
148     Public Function Intersection(s1 As IEnumerable(Of String), s2 As IEnumerable(Of String), Optional strict As Boolean = TrueAs String()
149         Return s1.Intersection(s2, AddressOf New __stringCompares(strict).Equals)
150     End Function
151
152     Private Structure __stringCompares
153         Dim mode As StringComparison
154
155         Sub New(strict As Boolean)
156             mode = If(strict, StringHelpers.StrictCompares, StringHelpers.NonStrictCompares)
157         End Sub
158
159         Public Overloads Function Equals(a As String, b As StringAs Boolean
160             Return String.Equals(a, b, mode)
161         End Function
162     End Structure
163 End Module