1
struct EnumerableGroupJoin{T,TKey,TI,SO,SI,OKS<:Function,IKS<:Function,RS<:Function} <: Enumerable
2 47
    outer::SO
3
    inner::SI
4
    outerKeySelector::OKS
5
    innerKeySelector::IKS
6
    resultSelector::RS
7
end
8

9 0
Base.eltype(::Type{EnumerableGroupJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}}) where {T,TKeyOuter,TI,SO,SI,OKS,IKS,RS} = T
10

11
function groupjoin(outer::Enumerable, inner::Enumerable, f_outerKeySelector::Function, outerKeySelector::Expr, f_innerKeySelector::Function, innerKeySelector::Expr, f_resultSelector::Function, resultSelector::Expr)
12 47
    TO = eltype(outer)
13
    TI = eltype(inner)
14 47
    TKeyOuter = Base._return_type(f_outerKeySelector, Tuple{TO,})
15 47
    TKeyInner = Base._return_type(f_innerKeySelector, Tuple{TI,})
16

17 47
    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 47
    T = Base._return_type(f_resultSelector, Tuple{TO,Array{TI,1}})
25

26 47
    OKS = typeof(f_outerKeySelector)
27 47
    IKS = typeof(f_innerKeySelector)
28 47
    RS = typeof(f_resultSelector)
29

30 47
    return EnumerableGroupJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}(outer,inner,f_outerKeySelector,f_innerKeySelector,f_resultSelector)
31
end
32

33
function Base.iterate(iter::EnumerableGroupJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}) where {T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}
34 47
    results = Array{T}(undef, 0)
35

36 39
    inner_dict = OrderedDict{TKeyOuter,Array{TI,1}}()
37 47
    for i in iter.inner
38 39
        key = iter.innerKeySelector(i)
39 47
        if !haskey(inner_dict, key)
40 47
            inner_dict[key] = Array{TI}(undef, 0)
41
        end
42 47
        push!(inner_dict[key], i)
43
    end
44

45 47
    for i in iter.outer
46
        outerKey = iter.outerKeySelector(i)
47 47
        if haskey(inner_dict,outerKey)
48 47
            g = inner_dict[outerKey]
49
        else
50 39
            g = Array{TI}(undef, 0)
51
        end
52 47
        push!(results, iter.resultSelector(i,g))
53
    end
54

55 47
    if length(results)==0
56 0
        return nothing
57
    end
58

59 47
    return results[1], (results,2)
60
end
61

62
function Base.iterate(iter::EnumerableGroupJoin{T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}, state) where {T,TKeyOuter,TI,SO,SI,OKS,IKS,RS}
63 17
    if state[2]>length(state[1])
64 17
        return nothing
65
    else
66 17
        return state[1][state[2]], (state[1], state[2]+1)
67
    end
68
end

Read our documentation on viewing source code .

Loading