Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@keta-sts136

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

4
Help us understand the problem. What is going on with this article?
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
keta-sts136
AIエンジニア&知財の人 ・高校を二回中退。高1で高認を所得し、大学で航空宇宙工学を学び、バイオマテリアルの研究者・ドローンの研究者を経て、AIの研究開発に従事している変な人。現在、無職でKaggle&atcoderで遊んでます。全力就活中なので気になった方声かけてください!

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?