Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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

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ではグローバルで実行したり、変数作ったりするとかなり実行速度が落ちることがわかりました。

keta-sts136
AIエンジニア&知財の人 高校を二回中退。高1で高認を所得し、大学で航空宇宙工学を学び、バイオマテリアルの研究者・ドローンの研究者を経て、AIの研究開発に従事している変な人
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした