2016-10-15 5 views
1

私はdoseqは各キーの例に見られるようリテラル{ ... }、の/ヴァルを反復することを理解してください、しかしHow to Iterate Over Map Keys and Values?doseq戻りnilと私はを反復して値を返すために、両方たいと思います。ハッシュのキー/値を反復処理して配列を返す方法は?

私はこのようになりますヴァル/キーオブジェクトがあります。

{:keyAAA [ val_element_one val_element_two val_element_three ] 
:keyBBB [ val_element_four val_element_five val_element_six ] 
:keyCCC [ val_element_seven val_element_eight val_element_nine ]} 

をし、私はこのような値を返す関数を作成したいと思います:

(:keyAAA :keyBBB :keyCCC) 

私は私ができる知っていますこの特定の例のために(keys map)を使用してください、しかし私は各key/val "要素"でもっと複雑なことをしようとしています。キー/ valオブジェクトを反復する関数が必要です。は、リスト/配列に各 "要素"を返します。

[ val_element_one 
    val_element_two 
    val_element_three 
    val_element_four 
    val_element_five 
    val_element_six 
    val_element_seven 
    val_element_eight 
    val_element_nine ] 

は基本的に、私はmapを探しています(またはreduceさらに良い)オブジェクトの各キー/ valを超える機能を入力します。具体的には、私はこのようなものを返す終わるしたいと思います。私はあなたが分かち合うのを助けてくれてとても感謝しています。

+0

私はあなたの代わりに私の[レオンGrapenthinの答え](http://stackoverflow.com/a/40073145/1562315)勉強し、受諾を検討をお勧めします。私はミフされません:)、 – Thumbnail

答えて

4

次のように私たちはあなたの特定の問題を扱うことができます。

(def data 
    '{ 
    :keyAAA [ val_element_one val_element_two val_element_three ] 
    :keyBBB [ val_element_four val_element_five val_element_six ] 
    :keyCCC [ val_element_seven val_element_eight val_element_nine ] 
    }) 

(->> data 
    vals 
    (apply concat) 
    vec) 

;[val_element_one val_element_two val_element_three val_element_four val_element_five val_element_six val_element_seven val_element_eight val_element_nine] 

しかし、私は、あなたが心の中で、より複雑な何かを持っていると思われます。その場合、this pageの機能がClojure Cookbookから役立つことがあります。これらはマップからマップを生成します。

doseqのようなものを探していて、それ以上の副作用がある場合は、forを探しているかもしれません。

+1

おかげで@私は私が必要なものを見つけたと思うreduce-kv –

+2

'(vec(mapcat second data)') –

2

受け入れられた答えは、あなたが求めるものを行うための古典的な方法を既に提供しているので、トランスデューサを中心に構築されたより現代的な言語機能を使用するこれらの代替方法を検討してください。

  1. (質問に尋ねたように)あなたが本当に配列をしたい場合は、concatの怠惰なシーケンスごとのステップのオーバーヘッドを取り除くためにeductionを使用します。Eductionがある

    (into-array (eduction cat (vals your-map))) 
    

コレクションごとに変換された結果を生成するコレクション型であり、配列に直接縮小され、効率よく縮小されるので、この場合に特に有用である。

    あなたは、配列が、Clojureのベクトルをしたくない場合は
  1. 、あなたはまだ怠惰ごとのステップを取り除くとは別に、

    (into [] cat (vals your-map)) 
    

ここで使用してトランスデューサを使用して怠惰なオーバーヘッドなしに逃げることができますオーバーヘッドでは、インプリメンテーションは内部的にClojureの一時データ構造を使用して挿入操作を高速化します。

これを行う方法はどちらも、トランスデューサ合成を使用してさらに拡張することができます。トランスデューサの使用方法を理解するためにトランスデューサの実装方法を理解する必要はありません。 g。あなたが本当にやりたいすべてが連結されている場合

(sequence (comp cat (filter pos?)) (vals your-map)) 
;; now it's up to the consumer of your collection how many 
;; elements will be calculated 
0

:あなたは後の時点で怠惰が必要行うことを実現した場合

(into [] (comp cat (filter pos?)) (vals your-map)) ; just the positive elements 

最後に、任意のコードを書き直すことなく、その戻って取得するのは簡単ですマップ内の値は、その後、ちょうどvalsconcatを使用します。

(apply concat (vals <your-map>)) 

それはこれよりも実際にはもっと複雑だ場合、あなたはmapcatを使用することができます。ここでは、値を連結するmapcatを使用することができます方法は次のとおりです。

(mapcat (fn [[k v]] ;; Or just use second 
      v) 
     <your-map>) 
関連する問題