【问题标题】:Julia: accumulating an array in a for loop (problem of local scope of loops)Julia:在 for 循环中累积数组(循环局部范围的问题)
【发布时间】:2020-09-26 12:19:01
【问题描述】:

我遇到了用for循环累加数组的问题(我的数组叫做condition_list,每一行存储一个唯一的参数配置)。

下面的代码是我想象的构建这个数组的代码:

param1_vals = [1.0f0 2.0f0 3.0f0]; # specific values here don't matter
param2_vals = [1.0f0 2.0f0 3.0f0]; # specific values here don't matter
param3_vals = [1.0f0 2.0f0 3.0f0]; # specific values here don't matter

condition_list = zeros(Float32, 1, 3) # initialize condition_list

for ii = 1:length(param1_vals)
        for jj = 1:length(param2_vals)
                for kk = 1:length(param3_vals)
                        row_to_stack = [param1_vals[ii], param2_vals[jj], param3_vals[kk])
                        condition_list = vcat(condition_list, row_to_stack)
                end
         end
end

condition_list = condition_list[2:end,:] # pop off that first row (leftover of the initialization)

因此,生成的 condition_list 的每一行都应该具有 param1_valsparam2_valsparam3_vals 的每个值的唯一配置。

我遇到的问题是关于局部变量的范围——当使用vcat 时,我在循环的最内层收到了condition_list is not defined 错误。如果我不能使用数组累积,解决这个问题的最儒略的方法是什么?或者也许有一些使用push! 的解决方案?

另外,有没有一种方法可以在不做我最后做的愚蠢的“弹出第一行”的事情的情况下积累一个数组?您可以从零行 3 列数组开始并在其上累积行吗?

【问题讨论】:

    标签: arrays for-loop scope julia accumulate


    【解决方案1】:

    第一条评论是,对于您来说,拥有一个惰性元组迭代器可能就足够了。在这种情况下,如果你写就足够了:

    res = Iterators.product(param1_vals, param2_vals, param3_vals)
    

    但是,如果您确实需要矩阵,请在 res 上运行以下代码:

    mapreduce(x -> hcat(x...), vcat, res)
    

    现在,如果您真的想使用您在代码中执行的操作,我会选择:

    condition_vec = Matrix{Float32}[]
    
    for ii = 1:length(param1_vals)
            for jj = 1:length(param2_vals)
                    for kk = 1:length(param3_vals)
                            row_to_stack = [param1_vals[ii] param2_vals[jj] param3_vals[kk]]
                            push!(condition_vec, row_to_stack)
                    end
             end
    end
    
    condition_list = reduce(vcat, condition_vec)
    

    但是,您可以简单地执行此代码有点过于复杂:

    condition_vec = Matrix{Float32}[]
    for p1 = param1_vals, p2 = param2_vals, p3 = param3_vals
        push!(condition_vec, [p1 p2 p3])
    end
    condition_list = reduce(vcat, condition_vec)
    

    没有中间索引。

    最后,您的代码无法正常工作,因为 condition_list 是一个全局变量,您必须编写:

    global condition_list = vcat(condition_list, row_to_stack)
    

    使其工作(请注意,Julia 会发生变化,很快就不需要了;此评论适用于 Julia 当前的 1.4.2 版本,或 1.0 版本之后的其他版本)。

    最后请注意:

    row_to_stack = [param1_vals[ii], param2_vals[jj], param3_vals[kk])
    

    语法不正确(您在行尾使用了) 而不是])。 此外,您使用, 不仅仅是在我的代码中使用空格来分隔值,这将为您创建一个列向量(不是具有 1 行的矩阵,因为我猜这是您使用 zeros 函数想要的)。

    如果您对此代码有更多疑问,请在评论中提问。

    【讨论】:

    • 或者mapreduce(Base.splat(hcat), vcat, res)
    • 非常感谢您的详细解释和替代选项!我想我会使用您首先建议的元组迭代器方法。问题是我对 Julia 中的 Iterators 函数没有什么经验,所以如果你愿意招待我,还有一个快速的问题:我想迭代这些“参数配置”(以前是 condition_list 的行矩阵)。如何从迭代器对象(上面的res)中获取一个元组(参数配置)?到目前为止,如果我在 for 循环中打印它们,我只能看到单个元组 (for cond_i in res)。
    • Iterators 的重点在于它是惰性的(即它不分配任何内存)。缺点是它没有实现,即你不能在它上面调用getindex,但你需要迭代地访问它们(例如使用for循环)。如果您希望能够进行索引,则只需运行collect(res),您将获得一个物化数组,您可以轻松地对其进行索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2023-03-04
    • 2021-01-24
    • 2020-01-19
    • 1970-01-01
    相关资源
    最近更新 更多