从Vec<(String,String)>创建Petgraph图.从JSON加载 [英] Create a Petgraph graph from a Vec<(String, String)> loaded from JSON
问题描述
我正在尝试创建一个宠物图 Graph
来自JSON数据. JSON包含图形的边缘,键表示起始顶点,值是相邻顶点的列表.可以生成一个带有边缘.
I'm trying to create a petgraph Graph
from JSON data. The JSON contains the edges of the graph, the key represents the starting vertex and the value is a list of adjacent vertices. It's possible to generate a graph with a vector of edges.
我设法创建了Vec<(String, String))>
,但没有按预期创建Vec<(&str, &str)>
.
I managed to create a Vec<(String, String))>
but not a Vec<(&str, &str)>
as expected.
extern crate petgraph;
extern crate serde_json;
use petgraph::prelude::*;
use serde_json::{Value, Error};
fn main() {
let data = r#"{
"A": [ "B" ],
"B": [ "C", "D" ],
"D": [ "E", "F" ]
}"#;
let json_value: Value = serde_json::from_str(data).unwrap();
let mut edges: Vec<(String, String)> = vec![];
if let Value::Object(map) = json_value {
for (from_edge, array) in &map {
if let &Value::Array(ref array_value) = array {
for edge in array_value {
if let &Value::String(ref to_edge) = edge {
edges.push((from_edge.clone(), to_edge.clone()))
}
}
}
}
}
// let graph = DiGraphMap::<&str, ()>::from_edges(edges);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct
// `std::string::String`, found &str
}
我尝试了不同的事情:
- 将图形类型更改为
DiGraphMap::<String, ()>
,但是它不接受. - 将
Vec<(String, String)>
转换为Vec<(&str, &str)>
.我阅读了这篇文章,但没有帮助 -
edges.push((&"a", &"b"))
有效,但edges.push((&from.clone(), &to.clone()))
无效.
- Change the graph type to
DiGraphMap::<String, ()>
, however it does not accept it. - Transform a
Vec<(String, String)>
into aVec<(&str, &str)>
. I read this post but it didn't help. edges.push((&"a", &"b"))
works but notedges.push((&from.clone(), &to.clone()))
.
这里可能有更好的提取边缘的方法.
There is probably a better way to extract the edges here.
推荐答案
将图形类型更改为
DiGraphMap::<String, ()>
,但是它不接受.
Change the graph type to
DiGraphMap::<String, ()>
, however it does not accept it.
A GraphMap
要求节点类型是可复制的. String
没有实现Copy
.
A GraphMap
requires that the node type be copyable. String
does not implement Copy
.
将
Vec<(String, String)>
转换为Vec<(&str, &str)>
如您所链接的问题中所述,这是不可能的.您可以 进行的操作是使用&str
创建一个 second Vec
并引用原始的String
s:
As mentioned in the question you linked, this is impossible. What you can do is create a second Vec
with &str
that reference the original String
s:
let a: Vec<(String, String)> = vec![("a".into(), "b".into())];
let b: Vec<(&str, &str)> = a.iter()
.map(|&(ref x, ref y)| (x.as_str(), y.as_str()))
.collect();
但是,在这种情况下不需要.取而代之的是,将JSON数据读入对地图进行建模的数据结构中(我选择了BTreeMap
),并将String
保留在那里.然后,您可以构造对这些String
的引用对的迭代器,从而从中构建图形:
However, that's not needed in this case. Instead, read the JSON data into a data structure that models a map (I chose BTreeMap
) and leave the String
s there. You can then construct an iterator of pairs of references to those String
s, building the graph from that:
extern crate petgraph;
extern crate serde_json;
use petgraph::prelude::*;
use std::collections::BTreeMap;
use std::iter;
fn main() {
let data = r#"{
"A": [ "B" ],
"B": [ "C", "D" ],
"D": [ "E", "F" ]
}"#;
let json_value: BTreeMap<String, Vec<String>> =
serde_json::from_str(data).unwrap();
let edges = json_value
.iter()
.flat_map(|(k, vs)| {
let vs = vs.iter().map(|v| v.as_str());
iter::repeat(k.as_str()).zip(vs)
});
let graph: DiGraphMap<_, ()> = edges.collect();
}
我需要将其封装到一个函数中
I need to encapsulate this into a function
这几乎是不可能的.由于JSON字符串包含UTF-8数据,因此Serde允许您获取对原始输入字符串的引用.您需要记住,您的graph
无法存活input
:
This is barely possible to do. Since JSON strings contain UTF-8 data, Serde allows you to get references to original input strings. You need to remember that your graph
cannot outlive input
:
fn main() {
let data = r#"{
"A": [ "B" ],
"B": [ "C", "D" ],
"D": [ "E", "F" ]
}"#;
let graph = example(data);
}
fn example(data: &str) -> serde_json::Result<DiGraphMap<&str, ()>> {
let json_value: BTreeMap<&str, Vec<&str>> = serde_json::from_str(data)?;
let edges = json_value
.into_iter()
.flat_map(|(k, vs)| iter::repeat(k).zip(vs));
Ok(edges.collect())
}
这篇关于从Vec<(String,String)>创建Petgraph图.从JSON加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!