结构数组字段的广播运算符 (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 并且该结构有许多字段,您可能会注意到差异)。