0
0

julia言語:複数の配列を一行で宣言

Last updated at Posted at 2024-09-07

前置き

julia言語での話ですが、他の言語でも当てはまるでしょう。
何も考えずに、コードを書いてると次のようなことが起こります。
(備忘録)


複数の変数の定義であれば、

a = b = c = d = 0

このように初期化しておいて、あとからプログラムの進行に応じて値を書き換えて使うことは自然に行うと思いますが、複数の配列について同じことをすると問題が起こります。具体的には

x = y = u = v = Array{Float64}(undef, 2, 2)

のようにすると、x, y, u, vの配列のいずれかの中身を、書き換えると他の3つも変更されます。

それもそのはず、配列は参照渡し1なので当たり前なのですが、
(x, y, u, vというシンボルが、すべて同じインスタンスを参照します)
一瞬「ん?」となりました。

解決策

解決策としては、

x = Array{Float64}(undef, 2, 2)
y = Array{Float64}(undef, 2, 2)
u = Array{Float64}(undef, 2, 2)
v = Array{Float64}(undef, 2, 2)

でも良いのですが、冗長すぎてすこし嫌なので

x, y, u, v = map(_->Array{Float64}(undef, 2, 2), 1:4)

こうします。
★解決!!★(※コメントでご指摘頂いた通り、もっといい方法がありました。→【補足】へ)

ーーー
一つ注意点があります。
mapは配列Vector{...}を返すので、

x = y = u = v = (map_->Array{Float64}(undef, 2, 2), 1:4)
typeof(x) # 結果:Vector{Matrix{Float64}}

つまり、x, y, u, vすべてに、Vector{Matrix{Float64}}のやつがぶち込まれています。なので、きちんと分割代入をするために、カンマを使ってあげましょう。
脳死でプログラムを書いていると間違えるので気をつけないとですね。
ーーー

【補足】(追記)
より良い方法をコメントでご指摘頂きました。ありがとうございます!
こちらのほうがスマートですね。

x, y, u, v = (similar(arrowmap, Float64) for _=1:4)

使い道

そもそも、なんでこんなことしたいのか?ですが、
グラフに矢印を描画するときに、4つの配列使いたくなるからです。
以下が例です。
この図のようなタイルの色に応じた矢印を描きたいとしたとき、下記のコードで描くことができます。
image.png

using Plots, MLStyle
n = 4
function generate_arrows(n)
    arrowmap = rand(1:4, n, n)
    return arrowmap
end

function putmap(arrowmap)
    heatmap(arrowmap, legend=false, aspect_ratio=1)
    l = 0.6 # 矢印の長さ
    direction = Array{String}(undef, size(arrowmap)) # これは使ってません
    x, y, u, v = map(_->Array{Float64}(undef, size(arrowmap)), 1:4)
    for i in 1:n
        for j in 1:n
            direction[i, j], x[i, j], y[i, j], u[i, j], v[i, j] = @match arrowmap[i, j] begin
            1 => ("↑", j,     i-l/2, 0.,  l)
            2 => ("→", j-l/2, i,      l, 0.)
            3 => ("↓", j,     i+l/2, 0., -l)
            4 => ("←", j+l/2, i,     -l, 0.)
            end
        end
    end
    quiver!(vec(x), vec(y), quiver=(vec(u), vec(v)), color=:white, lw=4)
    quiver!(vec(x), vec(y), quiver=(vec(u), vec(v)), color=:red, lw=2)
end

arrowmap = generate_arrows(n)
putmap(arrowmap)

参考文献

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0