让我们是一种把列表转换成准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