LoginSignup
6
4

More than 3 years have passed since last update.

【Julia初心者向け】Juliaで内包表記

Last updated at Posted at 2019-05-12

はじめに

今日は内包表記について書いていきます。

2019/05/13 追記:内包表記がforループより遅くなってしまったと書きましたが、
実行速度が遅くなってしまった原因はグローバルで実行したためでした。

リスト内包表記

内包表記の基本構文は以下の通りです。
[変数 for 変数 in イタレーター]


num = [n for n = 1:5]
> [1, 2, 3, 4, 5]

後置if文を置くことで、イタレーターで取り出す変数に条件をつけることができます。

a = [num for num in 1:10 if num % 2 == 0]
> [2, 4, 6, 8, 10]

前置if文も記載することで、リストに入れる値に分岐つけて処理をすることができます。
前置if文は複合式として書きます。

# 奇数は二乗します
a = [(if num % 2 == 0 num else num^2 end) for num in 1:10]
> [1, 2, 9, 4, 25, 6, 49, 8, 81, 10]

辞書内包表記

辞書内包表記はzip関数を使用します。

a = Dict(k for k = zip(["jp","USA","UK"], [0,1,2]))
> (  "USA" => 1, "UK"  => 2, "jp"  => 0)

zip関数はそれぞれの要素のタプルが返ってきます。
それぞれの要素をアンパッキングする場合は、下記のようにタプルで指定しないとエラーになります。

a = Dict((k,v) for (k,v) = zip(["jp","USA","UK"], [0,1,2]))
> (  "USA" => 1, "UK"  => 2, "jp"  => 0)

#これはエラーになります。↓
a = Dict((k,v) for k,v = zip(["jp","USA","UK"], [0,1,2]))
syntax: invalid iteration specification

それぞれの要素をアンパッキングすれば、下記のように条件を指定することができます。

a = Dict((k,v) for (k,v) = zip(["jp","USA","UK"], [0,1,2]) if v % 2 == 0)
> ("UK"  => 2, "jp"  => 0)

速度について

Pythonではforループでリストを作るより、リスト内包表記で作る方が速いです。
Juliaではどうか、検証してみました。

  • リスト内包表記

2019/05/13 追記: このベンチマークは正しい比較になっていないので、下記の追記を参照してください!

@time [num for num in 1:5 ]
> 0.026119 seconds (53.28 k allocations: 2.622 MiB)
  • for loop
@time begin
    begin
        b = []
        for num2 in 1:5
            push!(b,num2)
        end
        b
    end
end
> 0.000005 seconds (3 allocations: 208 bytes)

予想以上にforループがあまりにも早くて、びっくりです。
一応、確認のために複合式でも計測してみました、

@time (c = []; for num2 in 1:5 push!(c,num2) end; c)
> 0.000009 seconds (3 allocations: 208 bytes)

あまり、速度に変化がないので正しく計測できていることにします。
Juliaのforループは非常に高速なので、速度を気にしてリスト内包表記にする必要ないみたいです。

2019/05/13 追記

コメントでご指摘を受けまして、再度速度検証しました。
内包表記が速度が遅い原因は、グローバルで実行しているためです。
Juliaのドキュメントにも、グローバルは避けましょうと書いてあるのに、
グローバルでベンチマークとったことを反省・・・

適当に関数でラップすると爆速になりました。

f() = [num for num in 1:5 ]
@time f()
  0.000002 seconds (5 allocations: 288 bytes)
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

また、コメントでもご指摘のBenchmarkToolsを使うのが、ベンチマークの正しい取り方だと思います。
↑ドキュメントにもきちんとそう書いてあるorz

まとめ

Juliaの内包表記は簡単に記載できます。
しかし、速度面ではあまりメリットはありませんが、
リストの初期化処理などをシンプルに記載できるかと思います。

2019/05/13 追記 Juliaでも内包表記爆速です。
Juliaではグローバルで実行したり、変数作ったりするとかなり実行速度が落ちることがわかりました。

6
4
3

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
6
4