【问题标题】:Iterate through multiple variables (or whole matrix) in Julia遍历 Julia 中的多个变量(或整个矩阵)
【发布时间】:2018-09-25 09:13:28
【问题描述】:

我有一个 5 维数组想要对每个字段进行计算,并根据结果用“真”或“假”填充每个字段。现在我想知道是否有一种不使用 5 个“嵌套”循环的快速方法。 感谢您的帮助

编辑: 抱歉,问题不清楚。我需要用 5 个不同的变量进行计算,并且我已经检查了每个可能的组合。 我目前的做法是这样的:

while i<10
    while j<10
        while k < 10
            while l<10
                while m <10 
                    #some calculation which returns true or false
                    A[i,j,k,l,m]=f(i, j, k, l, m);
                m+=1;
                end
            l+=1;
            end
        k +=1;
        end
    j+=1; 
    end
i+=1; 
end

其中 A 是我的数组。现在我想知道是否有更有效的方法来做到这一点。 对不起,我希望现在更清楚。

【问题讨论】:

  • 鉴于下面的 cmets,我建议您更准确地给出您实际想要实现的目标(最好给出一个执行您想要的计算的示例代码)。
  • 你需要提供你的程序的一些细节。 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example
  • 如果f 是您想要应用于数组中每个元素的函数A,那么您可以通过使用点广播获得您想要的:B = f.(A)f 应该是一个返回 truefalse 的函数。现在,B 是一个与A 大小和形状相同的数组,包含布尔值。对于某些情况,比如“值是否大于零”,你可以写B = A .&gt; 0
  • 嗯。好的,所以您希望计算依赖于索引元组,而不是数组的值?
  • 这个问题现在对我来说似乎足够清晰和具体。按照@BogumiłKamiński 的建议使用CartesianIndices 是一个好方法。这是您想要的示例:B = [f(ind.I...,) for ind in CartesianIndices(A)].

标签: arrays matrix optimization multidimensional-array julia


【解决方案1】:

您可以像这样使用CartesianIndices 函数:

julia> x = Array{Tuple}(undef, 2,2,2,2,2);

julia> for idx in CartesianIndices(x)
       x[idx] = Tuple(idx)
       end

julia> x
2×2×2×2×2 Array{Tuple,5}:
[:, :, 1, 1, 1] =
 (1, 1, 1, 1, 1)  (1, 2, 1, 1, 1)
 (2, 1, 1, 1, 1)  (2, 2, 1, 1, 1)

[:, :, 2, 1, 1] =
 (1, 1, 2, 1, 1)  (1, 2, 2, 1, 1)
 (2, 1, 2, 1, 1)  (2, 2, 2, 1, 1)

[:, :, 1, 2, 1] =
 (1, 1, 1, 2, 1)  (1, 2, 1, 2, 1)
 (2, 1, 1, 2, 1)  (2, 2, 1, 2, 1)

[:, :, 2, 2, 1] =
 (1, 1, 2, 2, 1)  (1, 2, 2, 2, 1)
 (2, 1, 2, 2, 1)  (2, 2, 2, 2, 1)

[:, :, 1, 1, 2] =
 (1, 1, 1, 1, 2)  (1, 2, 1, 1, 2)
 (2, 1, 1, 1, 2)  (2, 2, 1, 1, 2)

[:, :, 2, 1, 2] =
 (1, 1, 2, 1, 2)  (1, 2, 2, 1, 2)
 (2, 1, 2, 1, 2)  (2, 2, 2, 1, 2)

[:, :, 1, 2, 2] =
 (1, 1, 1, 2, 2)  (1, 2, 1, 2, 2)
 (2, 1, 1, 2, 2)  (2, 2, 1, 2, 2)

[:, :, 2, 2, 2] =
 (1, 1, 2, 2, 2)  (1, 2, 2, 2, 2)
 (2, 1, 2, 2, 2)  (2, 2, 2, 2, 2)

The code stores in an entry `x[a,b,c,d,e]` a tuple `(a,b,c,d,e)`.

【讨论】:

  • 所以这给了我所有的可能性,对吧?有没有办法读出每个“坐标”来进行计算?
  • @Tschaix 你可以使用元组解包:v, w, x, y, z = Tuple(idx)
  • 你也可以索引到idx,就好像它是一个元组一样,例如idx[1] 会给你第一个维度,idx[2] 第二个等等。特别是,正如上面@DNF 所指出的,你可以写类似x .= f.(CartesianIndices(x) 来填充x,假设你写f 这样一种它接受CartesianIndex 的方式——那么你应该在函数中解压它或者写类似x .= (idx -&gt; f(Tuple(idx)...)).(CartesianIndices(x) 的东西来执行解压而不修改f 如果它接受5 个参数(再次 - 一切都发生在适当的位置)。
【解决方案2】:

您可以执行与一维矩阵相同的操作。

julia> A = rand(4,4,4,4,4);^C

julia> for (i, v) in enumerate(A)
         if v > 0.5 
           A[i] = 0
         end
       end

还有,比如:

   julia>map!(x->x>.5, A, A)

另外,如果原始数组是 Bool 以外的其他类型,我建议您使用不同的矩阵来分配结果值以确保类型稳定性。

【讨论】:

  • enumerate 将返回数组A 的线性索引作为元组中的第一个值。我知道@Tschaix 需要一个笛卡尔索引来了解数组的每个条目在每个维度中的索引是什么,并根据这个位置(而不是存储在数组中的值)计算true/fales
  • 他说“计算每个字段”。我理解为使用存储在数组中的值。现在不确定我是否又读过它。
  • 我们会看到问题何时澄清:)。
  • 您可以在我的答案中输入eachindex,但随后您将获得包含每个单元格的线性索引的元组,例如 1,2,3,4,5 ... 没有关于每个维度的信息。
  • 啊,是的,来自文档的a UnitRange if all inputs have fast linear indexing, a CartesianRange otherwise.
猜你喜欢
  • 2022-01-22
  • 2011-05-18
  • 2022-12-12
  • 2010-11-22
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多