结构数组字段的广播运算符 (Julia)
Broadcast operator over field of an array of structures (Julia)
我有一个数组实例化结构(相同类型)。我想更改这些结构的某个字段的值。出于性能原因,我想避免使用 for 循环。这是一个玩具代码来说明我的工作:
mutable struct foo
x
end
a,b = foo(5), foo(7)
arr = [a,b]
.-(getfield.(arr,:x),1)
我预计这会将 x 字段放入一个数组(指向实际 foo 的实际 x 字段的指针)然后将 -1 应用于所有这些。
当我调用 a,b
时,它们没有变化。调试后我知道这是因为getfield的broadcast()
将字段具体化(Broadcast.materialize
)到一个新数组中,即它被复制了。
是否有一种正确且高效的方法来做到这一点而无需循环?
谢谢
循环应该很快,正如 Matt B. 指出的那样。但是,如果你想避免循环(主要是为了方便起见),你可以这样写:
foreach(v -> v.x -= 1, arr)
(这实际上是一种循环,但我不希望它比循环更快)
或使用 StructArrays.jl,根据我的经验,这非常好。你想要的可以实现,例如像这样(使用你的arr
):
using StructArrays
arr2 = StructArray(arr)
arr2.x .-= 1
和 StructArrays.jl 负责从 arr2
.
的所有元素中的字段 x
中减去 1
EDIT 与结构集合上的 for
循环相比,如果您执行按列操作,您可以预期 StructArray
有时会更快(在您的示例中,该字段的类型为 Any
因此这应该不相关,但是如果它具有例如类型 Int
并且该结构有许多字段,您可能会注意到差异)。
我有一个数组实例化结构(相同类型)。我想更改这些结构的某个字段的值。出于性能原因,我想避免使用 for 循环。这是一个玩具代码来说明我的工作:
mutable struct foo
x
end
a,b = foo(5), foo(7)
arr = [a,b]
.-(getfield.(arr,:x),1)
我预计这会将 x 字段放入一个数组(指向实际 foo 的实际 x 字段的指针)然后将 -1 应用于所有这些。
当我调用 a,b
时,它们没有变化。调试后我知道这是因为getfield的broadcast()
将字段具体化(Broadcast.materialize
)到一个新数组中,即它被复制了。
是否有一种正确且高效的方法来做到这一点而无需循环?
谢谢
循环应该很快,正如 Matt B. 指出的那样。但是,如果你想避免循环(主要是为了方便起见),你可以这样写:
foreach(v -> v.x -= 1, arr)
(这实际上是一种循环,但我不希望它比循环更快)
或使用 StructArrays.jl,根据我的经验,这非常好。你想要的可以实现,例如像这样(使用你的arr
):
using StructArrays
arr2 = StructArray(arr)
arr2.x .-= 1
和 StructArrays.jl 负责从 arr2
.
x
中减去 1
EDIT 与结构集合上的 for
循环相比,如果您执行按列操作,您可以预期 StructArray
有时会更快(在您的示例中,该字段的类型为 Any
因此这应该不相关,但是如果它具有例如类型 Int
并且该结构有许多字段,您可能会注意到差异)。