我试图在各种网站上寻找答案,包括在这里看到一些看似相关的答案,但是我所尝试的一切都没有奏效。我正在尝试通过制作一个简单的JSON数据分析程序来学习Clojure。
我有以下示例数据(使用Cheshire来解析JSON文件,使用slurp
和parse-string
):
({:id "0",
:data [{:name "item1 x 1", :price {:GBP 9.99}} {:name "Delivery", :price {:GBP 3.49}}],
:date {:date "2014-01-12T01:21:28.000Z"},
:total {:GBP 1,
{:id "1",
:data [{:name "item2 x 1", :price {:GBP 9.99}}
{:name "item3 x 1", :price {:GBP 9.99}}
{:name "item4 x 1", :price {:GBP 9.99}}
{:name "Admin", :price {:GBP 3.49}}],
:date {:date "2013-01-12T07:37:04.000Z"},
:total {:GBP 2},
{:id "2",
:data [{:name "item6 x 1", :price {:GBP 9.99}}
{:name "item7 x 1", :price {:GBP 9.99}}
{:name "item4 x 2", :price {:GBP 9.99}}
{:name "item1 x 1", :price {:GBP 9.99}}
{:name "item2 x 1", :price {:GBP 9.99}}
{:name "Admin", :price {:GBP 3.49}}],
:date {:date "2012-01-15T13:29:54.000Z"},
:total {:GBP 3},
{:id "3",
:data [{:name "item8 x 1", :price {:GBP 9.99}}
{:name "item4 x 1", :price {:GBP 9.99}}
{:name "item5 x 1", :price {:GBP 9.99}}
{:name "item9 x 1", :price {:GBP 9.99}}
{:name "item4 x 1", :price {:GBP 9.99}}
{:name "Admin", :price {:GBP 3.49}}],
:date {:date "2014-01-17T06:22:23.000Z"},
:total {:GBP 4},
})
我相信这是地图或其他数据结构的持久向量(我正在努力克服clojure中的数据类型)。我正在尝试从中提取特定数据来回答分析问题,例如最常订购的项目,当天赚了多少钱等等。
我最初的问题只是尝试从此数据中的:name键中提取项目值。
我尝试使用map :data
将数据隔离到项目名称和价格,然后使用type
显示这是一个懒惰的序列。但是,我正在努力从名称键中获取数据(例如item1 x 1)。我已经尝试使用map函数和get-in函数无济于事。我认为这是由于数据的保存方式所以对此的任何解释都将非常感激!
这是我目前所坚持的,尽管如果有人确实想帮我解决更大的问题,然后获得最频繁的订单会很棒!
谢谢:)
答案 0 :(得分:3)
我不得不重新格式化您的数据,因为您遗漏了一些尾随的}
字符:
; Notice the single quote below!
(def data
'( {:id "0",
:data [{:name "item1 x 1", :price {:GBP 9.99}} {:name "Delivery", :price {:GBP 3.49}}],
:date {:date "2014-01-12T01:21:28.000Z"},
:total {:GBP 1}},
{:id "1",
:data [{:name "item2 x 1", :price {:GBP 9.99}}
{:name "item3 x 1", :price {:GBP 9.99}}
{:name "item4 x 1", :price {:GBP 9.99}}
{:name "Admin", :price {:GBP 3.49}}],
:date {:date "2013-01-12T07:37:04.000Z"},
:total {:GBP 2}},
{:id "2",
:data [{:name "item6 x 1", :price {:GBP 9.99}}
{:name "item7 x 1", :price {:GBP 1.23}}
{:name "item4 x 2", :price {:GBP 9.99}}
{:name "item1 x 1", :price {:GBP 9.99}}
{:name "item2 x 1", :price {:GBP 9.99}}
{:name "Admin", :price {:GBP 3.49}}],
:date {:date "2012-01-15T13:29:54.000Z"},
:total {:GBP 3}},
{:id "3",
:data [{:name "item8 x 1", :price {:GBP 9.99}}
{:name "item4 x 1", :price {:GBP 9.99}}
{:name "item5 x 1", :price {:GBP 9.99}}
{:name "item9 x 1", :price {:GBP 9.99}}
{:name "item4 x 1", :price {:GBP 9.99}}
{:name "Admin", :price {:GBP 3.49}}],
:date {:date "2014-01-17T06:22:23.000Z"},
:total {:GBP 4}},
)
)
这是4个地图的 持续列表 ,每个地图都有嵌套的矢量和地图。要获得" item7"的价格你需要这样的东西:
(->
(nth data 2)
(get-in [:data 1 :price :GBP]))
=> 1.23 ; where I changed the data to `1.23` to verify it worked
请务必结帐:
想到一个更简单的方法。 Use the unlazy
function,它将所有列表(懒惰或非懒惰)转换为向量。然后,您可以一步提取所需的项目:
(get-in (unlazy data) [2 :data 1 :price :GBP]) => 1.23
这是有效的,因为向量是一个关联数据结构,所以它就像一个从整数索引到元素值的映射。因此,get-in
可以用于地图和矢量"索引"。