1
|
|
struct EnumerableJoin{T,TKey,TI,SO,SI,OKS<:Function,IKS<:Function,RS<:Function} <: Enumerable
|
2
|
23
|
outer::SO
|
3
|
|
inner::SI
|
4
|
|
outerKeySelector::OKS
|
5
|
|
innerKeySelector::IKS
|
6
|
|
resultSelector::RS
|
7
|
|
end
|
8
|
|
|
9
|
0
|
Base.eltype(::Type{EnumerableJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}}) where {T,TKeyOuter,TI,SO,SI,OKS,IKS,RS} = T
|
10
|
|
|
11
|
|
function join(outer::Enumerable, inner::Enumerable, f_outerKeySelector::Function, outerKeySelector::Expr, f_innerKeySelector::Function, innerKeySelector::Expr, f_resultSelector::Function, resultSelector::Expr)
|
12
|
23
|
TO = eltype(outer)
|
13
|
|
TI = eltype(inner)
|
14
|
23
|
TKeyOuter = Base._return_type(f_outerKeySelector, Tuple{TO,})
|
15
|
23
|
TKeyInner = Base._return_type(f_innerKeySelector, Tuple{TI,})
|
16
|
|
|
17
|
23
|
if TKeyOuter!=TKeyInner
|
18
|
0
|
error("The keys in the join clause have different types, $TKeyOuter and $TKeyInner.")
|
19
|
|
end
|
20
|
|
|
21
|
|
SO = typeof(outer)
|
22
|
|
SI = typeof(inner)
|
23
|
|
|
24
|
23
|
T = Base._return_type(f_resultSelector, Tuple{TO,TI})
|
25
|
|
|
26
|
23
|
OKS = typeof(f_outerKeySelector)
|
27
|
23
|
IKS = typeof(f_innerKeySelector)
|
28
|
23
|
RS = typeof(f_resultSelector)
|
29
|
|
|
30
|
23
|
return EnumerableJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}(outer,inner,f_outerKeySelector,f_innerKeySelector,f_resultSelector)
|
31
|
|
end
|
32
|
|
|
33
|
|
function Base.iterate(iter::EnumerableJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}) where {T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}
|
34
|
23
|
results = Array{T}(undef, 0)
|
35
|
|
|
36
|
18
|
inner_dict = OrderedDict{TKeyOuter,Array{TI,1}}()
|
37
|
23
|
for i in iter.inner
|
38
|
18
|
key = iter.innerKeySelector(i)
|
39
|
23
|
if !haskey(inner_dict, key)
|
40
|
23
|
inner_dict[key] = Array{TI}(undef, 0)
|
41
|
|
end
|
42
|
23
|
push!(inner_dict[key], i)
|
43
|
|
end
|
44
|
|
|
45
|
23
|
for i in iter.outer
|
46
|
|
outerKey = iter.outerKeySelector(i)
|
47
|
23
|
if haskey(inner_dict,outerKey)
|
48
|
23
|
for j in inner_dict[outerKey]
|
49
|
23
|
push!(results, iter.resultSelector(i,j))
|
50
|
|
end
|
51
|
|
end
|
52
|
|
end
|
53
|
|
|
54
|
23
|
if length(results)==0
|
55
|
0
|
return nothing
|
56
|
|
end
|
57
|
|
|
58
|
23
|
return results[1], (results, 2)
|
59
|
|
end
|
60
|
|
|
61
|
|
function Base.iterate(iter::EnumerableJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}, state) where {T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}
|
62
|
10
|
if state[2]>length(state[1])
|
63
|
10
|
return nothing
|
64
|
|
else
|
65
|
10
|
return state[1][state[2]], (state[1], state[2]+1)
|
66
|
|
end
|
67
|
|
end
|