首页 > 解决方案 > Julia:跨不同结构实例的字段应用函数

问题描述

假设我有一个数组my_array,其元素是 的实例myType,因此数组类型由 给出Array{myType,1}

现在假设myTypewithin的每个实例my_array都有一些x存储数据向量的字段(例如typeof(instance_of_myType.x) == Array{Float32,1})。

如果我知道数组中结构x的每个实例的不同字段具有相同的大小,有没有一种方法可以跨数组中所有实例myType的不同字段广播函数(例如平均或求和),这将给我一个向量,这是将函数应用于结构体的所有字段的结果?有没有办法在没有for循环的情况下做到这一点,基本上就是我要问的?xmyTypeArray{Float32,1}xmy_array

标签: structtypesjuliaarray-broadcastingbroadcasting

解决方案


这应该有效(除非您已getproperty为您的类型覆盖):

sum.(getproperty.(my_array, :x))

这是一个比较广播和使用理解的完整示例:

julia> struct A{T}
              x::T
              end

julia> my_array = [A(collect(i:i+3)) for i in 1:3]
3-element Array{A{Array{Int64,1}},1}:
 A{Array{Int64,1}}([1, 2, 3, 4])
 A{Array{Int64,1}}([2, 3, 4, 5])
 A{Array{Int64,1}}([3, 4, 5, 6])

julia> sum.(getproperty.(my_array, :x))
3-element Array{Int64,1}:
 10
 14
 18

julia> [sum(v.x) for v in my_array]
3-element Array{Int64,1}:
 10
 14
 18

现在一个有趣的例子是,如果你想应用一个函数,例如sum跨结构中字段x的各个元素。你可以得到这样的结果:

julia> sum(getproperty.(my_array, :x))
4-element Array{Int64,1}:
  6
  9
 12
 15

(请注意,这种情况下唯一的区别是没有.after sum

或者像这样

julia> sum(v -> v.x, my_array)
4-element Array{Int64,1}:
  6
  9
 12
 15

编辑

所以一般的方法是:

julia> tmp = getproperty.(my_array, :x)
3-element Array{Array{Int64,1},1}:
 [1, 2, 3, 4]
 [2, 3, 4, 5]
 [3, 4, 5, 6]

现在你可以写:

 [fun(getindex.(tmp, i)) for i in eachindex(tmp...)]

假设fun将向量作为参数。

如果你想使用一个优秀的 SplitApplyCombine.jl 包,你可以这样写:

fun.(invert(getproperty.(my_array, :x)))

asinvert函数完全符合您的需要,例如:

  julia> invert([[1,2,3], [4,5,6]])
  3-element Array{Array{Int64,1},1}:
   [1, 4]
   [2, 5]
   [3, 6]

推荐阅读