2016-11-05 13 views
0

私はちょうどhaskellを学んでいて、すべての人が怖いモナドでさえも大したことではないようです。しかし、私は実際の練習的なものにまったく乗り遅れることはありません。jsonデータover map haskell

haskellの最初の実用的な仕事は次の通りです: バイナリファイルの形式を記述したJSONがあれば、そのファイルを解析します。

JSONには、番号や文字列としてのエンドポイントを持つリストなどのアソシエートリスト(辞書)のリストを含む深くネストされた構造があります。 まず最初に、他のエンドポイント(jsonsデータ用のファンクタクラスを持つ)をいくつかの文字列を特に数値に変換することができるようにしたいと思います。また、これらのエンドポイントもすべて折り畳むことができればうれしいでしょう。

私は簡単にいくつかのpythonコードを思い付いた。しかし、haskellで遠くまで行くことはできません。 だから、あなたはハズケで何かを実装するためのあなたの提案ですか?ライブラリを最大限に活用し、すべてのものを最初から手書きしないという解決策のアドバイスを聞くことは本当にうれしいことです。

ありがとうございます!

は---私はpythonで持っているものの 例

いくつかのヘルパー関数を追加しました:ネストされたJSONデータに対する

islist = lambda l: isinstance(l, collections.Iterable) and not isinstance(l, (str, bytes)) 
isdict = lambda d: isinstance(d, collections.Mapping) 
isiter = lambda i: islist(i) or isdict(i) 

def iterable(d): 
    if isdict(d): 
     i = d.items() 
    elif islist(d): 
     i = enumerate(d) 
    else: 
     raise ValueError 
    return i 

イテレータ:

def nested_iter(nested, f = lambda *args: None): 
    for key, value in iterable(nested): 
     if not isiter(value): 
      f(nested, key) 
      yield key, value 
     else: 
      yield from nested_iter(value, f) 

を今、私はいくつかの数字を置き換えることができますキーのリスト:

def list_from_num(d, k): 
    if type(d[k]) == int: 
     d[k] = [k]*d[k] 
list(nested_iter(typedef, list_from_num)) 

またはIと同じキー名と他のいくつかのネストされたデータといくつかの文字列を置き換えることができ

def nest_dicts(defs, d, k): 
    if d[k] in defs.keys(): 
     d[k] = deepcopy(defs[d[k]]) 
     if isiter(d[k]): 
      list(nested_iter(d[k], partial(nest_dicts, defs))) 
list(nested_iter(typedef, partial(nest_dicts, typedef))) 

か、単にデータ

list(nested_iter(d)) 

バイナリを解析すると、もう少し進化しているが、それはより多くの何物でもありませんを平らにすることができますイテレータにもう1つの関数を渡すとして

+0

あなたがしたいことのいくつかの並べ替えの例はいいですが、私はあなたがそう探していると思います['lens'](https://hackage.haskell.org/package/lens)や[' lens-aeson'](https://hackage.haskell.org/package/lens-aeson)のようなメーピングがあります。 – Alec

+0

はい...誰かがすでに私のレンズをお勧めしました。私はまだ勉強していません。ファンクター、アプリケーション、モナド、変圧器をちょっと手に入れました。 haskellで実用的なものを作り始めることを学ぶには非常に多くのものがあります... – aliko

+0

何か簡単に始めたいなら、[aeson'](https://hackage.haskell)を使ってJSONをHaskellのデータにマッピングすることができます.org/package/aeson)。それで、あなたは普通の変換をすることができます。 'lens'ビットはネストされたデータを操作するのが本当にいいです。 – Alec

答えて

0

これは私のソリューションです。 Control.Lens、Data.Aeson.Lens、Control.Lens.Platedを使用します。

UniplateまたはLens.Platedの変換を使用して値を変換できます。同じキーを持つデータで代替文字列に

n2k :: T.Text -> Value -> Value --import qualified Data.Text as T 
n2k s (Number x) 
    | isInteger x = case toBoundedInteger x of 
    Just n -> Array (V.replicate n (String s)) -- import qualified Data.Vector as V 
    _   -> Number x 
    | otherwise = Number x 
n2k _ v = v 

f (Object o) = Object $ imap n2k o --imap from Data.Map.Lens 
f x   = x 

j2 = transform f j --transform JSON j using function f 

-- o is hashmap where we are looking for keys to substitute strings 
h (String s) = fromMaybe (String s) (H.lookup s o) --import qualified Data.HashMap.Lazy as H 
h x   = x 

j2 = transform h j 

ちょうどリストにすべての数字を取得し、その番号の長さのキー値のリストと、各数値を代入する例えば

l = [x | Number x <- universe j] 
関連する問題