Find each instance of the smaller matrix in the larger and create a NamedTuple (;a,b)
[
:X a _
b _ :Y
]
[
1 2 3
:X 1 2
3 4 :Y
:X 1 2
4 5 :Y
10 11 12
:X 3 3
7 4 :Y
6 7 8
8 7 6
]
#output
[
(a=1,b=3)
(a=1,b=4)
(a=3,b=7)
]
Guess, this needs a bit of help as you might want to match on overlapping/non-overlapping rows etc. Nevertheless, here is a way using Match.jl
:
julia> using IterTools, Match
julia> Z = [1 2 3; :X 1 2; 3 4 :Y; :X 1 2; 4 5 :Y; 10 11 12; :X 3 3; 7 4 :Y; 6 7 8; 8 7 6];
julia> foo(x) = @match x begin
# Note: @match does not work on matrices directly
([:X, a, _], [b, _, :Y]) => (; a, b)
_ => missing
end
foo (generic function with 1 method)
# Note: IterTools to get overlapping partitions of two rows
julia> skipmissing(foo.(IterTools.partition(eachrow(Z), 2, 1))) |> collect
3-element Vector{@NamedTuple{a::Int64, b::Int64}}:
(a = 1, b = 3)
(a = 1, b = 4)
(a = 3, b = 7)
5 Likes
m=[
:X :a 0
:b 0 :Y
]
M=[
1 2 3
:X 1 2
3 4 :Y
:X 1 2
4 5 :Y
10 11 12
:X 3 3
7 4 5
:X 7 8
8 7 :Y
]
#output
[
(a=1,b=3)
(a=1,b=4)
(a=3,b=7)
]
rm,cm = size(m)
r,c=size(M)
AX=findall(e->e==:X ,M)
BY=AX.+CartesianIndex(rm-1,cm-1)
y=findall(e->M[e]==:Y,BY)
[(;a=M[x+CartesianIndex(0,1)],b=M[x+CartesianIndex(1,0)]) for x in AX[y]]
1 Like
stretching a bit more in an attempt to be more general
[(;zip((m[1,2],m[2,1]),(M[x+CartesianIndex(0,1)],M[x+CartesianIndex(1,0)]))...) for x in AX[y]]