问题
I am currently studying newick format. https://en.wikipedia.org/wiki/Newick_format I have a newick string of a tree
(A,B,(C,D)E)F;
How to convert this string into a hierarchical javascript object like
tree = {
name: 'F',
children: [{
name: 'A'
}, {
name: 'B'
}, {
name: 'E',
children: [{
name: 'C'
}, {
name: 'D'
}]
}]
}
回答1:
The code below should work correctly with any input similar to your example.
However, it assumes that each node is identified with a single character. You'd have to modify it to support longer symbols.
Also, this code is not bullet-proof and will break without any warning on invalid input strings.
The main idea is to parse the string in reverse order and keep track of node hierarchy using the stack array.
var newick = '(A,B,(C,D)E)F',
stack = [],
child,
root = [],
node = root;
newick.split('').reverse().forEach(function(n) {
switch(n) {
case ')':
// ')' => begin child node
stack.push(node);
node = child.children = [];
break;
case '(':
// '(' => end of child node
node = stack.pop();
break;
case ',':
// ',' => separator (ignored)
break;
default:
// assume all other characters are node names
node.push(child = { name: n });
break;
}
});
And here is a simple function that will dump the resulting structure:
var dmp;
(dmp = function(node, level) {
node.forEach(function(n) {
console.log(Array(level).join('-') + n.name);
n.children && dmp(n.children, level + 1);
});
})(root, 1);
Output:
F
-E
--D
--C
-B
-A
回答2:
You might want to look at taking substrings of the original tree and writing a recursive function that stores the removed letters per heirarchical level.
Possible starter:
var str = "Z,I,(A,B,(C,D)E)F,G,H";
var firstClose = str.indexOf("(");
var lastClose = str.lastIndexOf(")");
console.log(firstClose);
console.log(lastClose);
var remainingTree = str.substr(firstClose , lastClose);
console.log(remainingTree);
var lastLetterStr = (str.substring( lastClose + 1 ) );
var lastLetterArray = lastLetterStr.split(',');
var firstLetterStr = str.substring(0,firstClose-1)
var firstLetterArray = firstLetterStr.split(',')
console.log(lastLetterArray);
console.log(firstLetterArray);
Apply the same steps to the remainingTree
string until the string is empty and then create the tree
object? You'll have to include some logic so that the function knows how to associate for example (C,D)
as children of E
when building up the time
object
JS Fiddle
回答3:
You can try NewickJS
Example:
var newick = new Newick('(A:0.1,B:0.2,(C:0.3,D:0.4)E:0.5)F');
Or you can use static method:
var tree = Newick.parse('(A:0.1,B:0.2,(C:0.3,D:0.4)E:0.5)F');
The result:
{
name: "F",
branchset: [
{
name: "A",
length: 0.1
},
{
name: "B",
length: 0.2
},
{
name: "E",
length: 0.5,
branchset: [
{
name: "C",
length: 0.3
},
{
name: "D",
length: 0.4
}]
}]
}
NewickJS at GitHub
来源:https://stackoverflow.com/questions/38310065/how-to-convert-newick-tree-format-to-tree-like-hierarchical-javascript-object