讓我們是一種把列表轉換成準JSON字符串的函數:`Reduce`,而不是`<< - `
as.cypher.list = function(l){
dots = l
reserved = c("ID", "label")
properties = dots[!names(dots) %in% reserved]
properties = gsub("',", "', ", # adds spaces after commas
gsub('"', "'", # replaces " with '
gsub('"([^"]+)":', "\\1:", # removes " around key names
toJSON(rapply(properties, as.character)))))
label = if(is.null(dots[["label"]])) "" else paste0(":", dots[["label"]])
ID = if(is.null(dots[["ID"]])) NA_character_ else dots[["ID"]]
query = sprintf("%s%s", label, properties)
return(query)
}
例如:
as.cypher.list(list(label="AA", a=1, b="foo", name="bar"))
# [1] ":AA{a:'1', b:'foo', name:'bar'}"
現在讓我們:
query = "MATCH {n}, {ae} RETURN n"
nodes = list(n=list(label="AA", a=1, b="foo", name="bar"),
ae=list(label="BB", b=2))
如何將nodes
列表中的值替換爲query
,以便每個列表名稱與子字符串內部匹配query
?取代後的最終理想的結果是:
query
# [1] "MATCH (n:AA{a:'1', b:'foo', name:'bar'}), (ae:BB{b:'2'}) RETURN n"
我可以做到這一點:
add_param = function(nm, val){
query <<- gsub(paste0("{", nm, "}"),
paste0("(", nm, as.cypher.list(val),")"),
query, fixed = T)
}
Map(add_param, names(nodes), nodes)
# $n
# [1] "MATCH (n:AA{a:'1', b:'foo', name:'bar'}), {ae} RETURN n"
#
# $ae
# [1] "MATCH (n:AA{a:'1', b:'foo', name:'vser'}), (ae:BB{b:'2'}) RETURN n"
但是請注意使用的<<-
這是相當尷尬的。
如何在這種情況下使用Reduce()
?
爲什麼不寫一個'for'循環?似乎更容易 – konvas 2014-10-10 15:53:46
想學習MapReduce風格。此外,應避免循環。 – 2014-10-10 15:58:28
for循環的糟糕用法絕對應該避免。在你的情況下,for循環很好,因爲你只是循環遍歷'seq_along(nodes)'並且只更新循環內的變量'query',所以非常好。 – konvas 2014-10-10 16:00:45