我是Clojure的新手并尝试从JSON中检索密钥列表。 初始数据结构是一个从目录中悄悄出现的JSON文件数组,下面是其中一个文件的示例(因此它实际上是以下列表):
study(title='gap detector', overlay=true)
//plotshape(<condition>, <options>) // condition must be true to plot something
is_percentage_increase = if (close-close[1])/close[1] > 0.05
true
plotshape(is_percentage_increase, style=shape.circle, color=green)
我需要获得一个&#34;描述&#34;价值除了&#34;交货&#34;,只是&#34; SKU-1074 x 1&#34;对于每个文件中的每个订单。然后我在另一个函数中使用此列表链接到产品ID。 我之前已经完成了半实现,但它似乎没有迭代所有内容只有一个订单,我编辑的以下代码试图实现这一点:
[
{
"id": "d588596f-c8ce-41de-85f6-12321a2e1888",
"lines": [
{
"description": "SKU-1079 x 1",
"price": {
"GBP": 14.99
}
},
{
"description": "Delivery",
"price": {
"GBP": 3.49
}
}
],
"date": {
"date": "2016-09-07T00:53:31.000Z"
},
"total": {
"GBP": 18.48
},
"invoice-address": [
"93",
"Westhorpe Road",
"Inverness",
"IV1 3WU"
],
"delivery-address": [
"93",
"Westhorpe Road",
"Inverness",
"IV1 3WU"
]
},
{
"id": "f1f471b2-5bf7-404e-9345-dcccdfba5c8a",
"lines": [
{
"description": "SKU-1003 x 1",
"price": {
"GBP": 14.99
}
},
{
"description": "SKU-1015 x 1",
"price": {
"GBP": 14.99
}
},
{
"description": "SKU-1086 x 1",
"price": {
"GBP": 14.99
}
},
{
"description": "SKU-1029 x 1",
"price": {
"GBP": 14.99
}
},
{
"description": "SKU-1074 x 1",
"price": {
"GBP": 14.99
}
},
{
"description": "Delivery",
"price": {
"GBP": 3.49
}
}
],
"date": {
"date": "2016-09-07T01:15:48.000Z"
},
"total": {
"GBP": 78.44
},
"invoice-address": [
"18",
"Barbican",
"East Central London",
"EC17 4HP"
],
"delivery-address": [
"18",
"Barbican",
"East Central London",
"EC17 4HP"
]
}
]
尝试了很多代码的迭代,主要是使用嵌套映射,for和匿名函数,但我似乎总是返回的是一个nil值列表。
以下从ordersData地图中检索第一个订单的行,但我无法理解如何在此级别进行迭代。在命令式语言中,我可能使用嵌套循环但不完全确定。
(defn getOrders [year month day]
(let [fs (filter #(.isFile %) (file-seq (clojure.java.io/file (str "data/orders/" year "/" month "/" day))))
ordersData (map #(json/read-str (slurp %) :key-fn keyword) fs)
getLines (fn [x] (map :lines x))
getDescription (fn [x] (map #(get % :description)))]
;(for [x (map #(getLines %) ordersData)] (remove #{"Delivery"} (map #(get % :description) x)))
(->> (for [x ordersData] (for [y x] (for [z y] z)))
(map (fn [x] (map (fn [y] y) x))) ;Tried many different maps/fors here
)
)
)
答案 0 :(得分:2)
这是一种相当简单的方法:
(def my-maps (json/read-str "json goes here"))
定义一个将在JSON中的每个顶级地图上运行的函数:
(defn descriptions [m]
(->> (get m "lines") ;; get the lines from the map
(map #(get % "description")) ;; get the description values
(remove #{"Delivery"}))) ;; remove any "Delivery" values
这个descriptions
函数可能更有效,但我认为这是一个很好的解释性示例。
然后{J}映射的map
:
(map descriptions my-maps)
=> (("SKU-1079 x 1")
("SKU-1003 x 1" "SKU-1015 x 1" "SKU-1086 x 1" "SKU-1029 x 1" "SKU-1074 x 1"))
要获得您想要的完全平坦的列表,请将map
替换为mapcat
:
(mapcat descriptions my-maps)
=> ("SKU-1079 x 1" "SKU-1003 x 1" "SKU-1015 x 1" "SKU-1086 x 1" "SKU-1029 x 1" "SKU-1074 x 1")