让我们有一个将列表转换为准JSON字符串的函数:
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()
?
答案 0 :(得分:2)
这里唯一的小问题是,当您在命名列表上使用Reduce
时,您无法访问该函数中的名称。解决这个问题的一种方法是只使用数据嵌入名称。您可以执行Map(list, names(nodes), nodes)
之类的转换。然后,一旦你拥有了这个对象,就可以迭代完成具有你需要的所有信息,你可以使用Reduce
Reduce(function(q,n) {
nm <- n[[1]]
val <- n[[2]]
gsub(paste0("{", nm, "}"),
paste0("(", nm, as.cypher.list(val),")"),
q, fixed = T)
}, Map(list, names(nodes), nodes), init=query)
# [1] "MATCH (n:AA{a:'1', b:'foo', name:'bar'}), (ae:BB{b:'2'}) RETURN n"
您还可以考虑使用regmatches()
进行提取/替换。这是一个这样的策略
tnodes <- mapply(function(nm, val) paste0("(", nm, as.cypher.list(val),")"),
names(nodes), nodes)
query <- "MATCH {n}, {ae} RETURN n"
m <- gregexpr("\\{[^}]+\\}", query)
regmatches(query, m) <- lapply(regmatches(query, m), function(x) {
names <- substr(x, 2, nchar(x)-1)
tnodes[names]
})
query
# [1] "MATCH (n:AA{a:'1', b:'foo', name:'bar'}), (ae:BB{b:'2'}) RETURN n"
基本上我们首先缓存节点的转换值,然后查找所有&#39; {xx}&#39;令牌并用相应的值替换它们。