2017-11-14 12 views
2

Juliaの辞書dには何千ものキーが含まれているとします。各キーはシンボルであり、各値は配列です。今、私は繰り返して新しい変数をk2, k3, k4, ..., k10定義するとし辞書を反復することで新しい変数を効率的に定義する方法(Julia)

:[S1]私は

k1を介して可変​​に= D記号:S1に関連付けられた値にアクセスし、それを割り当てることができます:S1 ... :S10(辞書のすべてのキーではありません)と同じ手順です。それを行う最も効率的な方法は何ですか?私はこれがメタプログラミングを使って解決できるという印象を持っていますが、それについてはわかりません。

+2

本当にこれをやりたいですか?ほとんどの場合、 'k = [];のような配列を作るほうがいいでしょう。 (d)push!(k、val)end'の値をvalに代入し、 'kn'の代わりに' k [n] 'として値にアクセスします。スクラッチでは、 'k = collect(values(d))'を行うことができます。 – DNF

+0

実際、私は実際のプログラムでこれをやりたいとは思っていません。名前空間にはあまりにも多くの変数が含まれています。私は辞書全体を反復する必要がある場合あなたのヒントは良いですが、私は特定のキーに興味があることを思い出してください。 – dapias

+1

次に: 'k = collect(Iterators.take(values(d)、10))'? – DNF

答えて

5

簡単な方法はParameters.jlです。

using Parameters 
d = Dict{Symbol,Any}(:a=>5.0,:b=>2,:c=>"Hi!") 
@unpack a, c = d 
a == 5.0 #true 
c == "Hi!" #true 

ここで、これは評価を使用しません。

3

コンパイル時に特殊キーがすべてわかっている場合は、Chris Rackauckas's answer を使用することをお勧めします。これははるかに悪いことではなく、ローカル変数の作成にも役立ちます。

何らかの理由で実行時にのみ知られている場合は、 次のようにすることができます。 (コンパイル時に知っていない変数を作成する必要があるのは実際はかなり奇妙だと思いますが)

@evalはあなたの友人*です。しかし、あなたは新しいローカル変数を導入し、これを使用することはできません eval(:($key = $value))

注:the manual @eval $key = $value

それともeval()が引用された表現を取る関数形式を使用することができますを参照してください。 evalは常にモジュールスコープで実行されます。 そして、それは正直なところeval * a intentional restriction for performance reasons

julia> d = Dict(k => rand(3) for k in [:a, :b1, :c2, :c1]) 
Dict{Symbol,Array{Float64,1}} with 4 entries: 
    :a => [0.446723, 0.0853543, 0.476118] 
    :b1 => [0.212369, 0.846363, 0.854601] 
    :c1 => [0.542332, 0.885369, 0.635742] 
    :c2 => [0.118641, 0.987508, 0.578754] 

julia> for (k,v) in d 
      #create constants for only ones starting with `c` 
      if first(string(k)) == c 
       @eval const $k = $v 
      end 
     end 


julia> c2 
3-element Array{Float64,1}: 
    0.118641 
    0.987508 
    0.578754 

であるあなたの友人ではありません。 しかし、実行時の値に基づいてコードを生成するこの暗い道を歩くだけで十分です。 (@generateは、実行時の型に基づいてコードを生成したいと思っているほんの少ししかありません)。 ランタイム情報に基づいてコードを生成する必要があるこのような状況では、設計ミスを起こしていないかどうかを検討してください。

+1

私が聞いた限りでは、 'eval'はあなたの友人ではありません。おそらく、それは間違った質問に対する答えです。 – DNF

+2

もしあなたの友人でないなら、少なくとも 'eval'は実行時の値に基づいてコードを生成するこの暗い道を歩くのに十分な唯一の仲間です。 ( '@ generate'は実行時の型に基づいてコードを生成したいと思っているだけです) –

+1

[DataFramesMeta.jl](https://github.com/JuliaStats/DataFramesMeta.jl)のようなものがおそらくもっと良いでしょう。' ' @ with' –

2

あなたが本当にK1を持つようにしたい場合は、K2、...、K10、...あなたはリンドンさんよりも少し複雑にevalを使用することができます。

for (i,j) in enumerate(d) 
     @eval $(Symbol("k$i")) = $j.second 
end 

警告:はeval()グローバルスコープを使用しますしたがって、あなたが関数k1 ... knの中でこれを使うとしても、グローバル変数になります。

+0

この回答は素晴らしいです。ありがとうございました!私はdictのすべてのキーのためにそれをしたくないと言って忘れてしまった。 – dapias

関連する問題