如何删除树中的单个 children?
How do I remove single children in a tree?
给定以下树:
{
"name": "svg",
"type": "element",
"value": "",
"attributes": {
"xmlns": "http://www.w3.org/2000/svg",
"width": "1440",
"height": "1080"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"fill": "#627580"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}, {
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}]
}]
}]
}]
}
...这是 HTML:
的表示
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1080">
<g>
<g>
<g fill="#627580">
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
</g>
</g>
</g>
</svg>
我如何在 JavaScript 中递归地转换此数据结构,以便所有只有一个 child <g>
的组 <g>
被折叠并且它们的 child ren 被分配到其 parent?
预期结果是这样的:
{
"name": "svg",
"type": "element",
"value": "",
"attributes": {
"xmlns": "http://www.w3.org/2000/svg",
"width": "1440",
"height": "1080"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}, {
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}]
}]
}
...这是 HTML:
的表示
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1080">
<g>
<g fill="#627580">
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
</g>
</g>
</svg>
理想情况下,不应有一个 <g>
元素与单个 child <g>
剩余。换句话说:
<g>
<g>
...
</g>
</g>
将转化为
<g>
...
</g>
这是我的尝试:
const collapseGroups = node => {
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
collapseGroups(child)
})
if (node.name == 'g' &&
node.children.length == 1 &&
node.children[0].name == 'g') {
node.children = node.children[0].children;
}
}
}
注意:我输入的是一个SVG文件,已经自动解析成上面提到的JS object.
您可以在每个节点上使用递归函数。如果它检测到它是“g”类型,并且只有一个子节点,则该节点吸收该子节点,并合并属性 属性:
function simplify(node) {
return node.name === 'g' && node.children.length === 1
&& node.children[0].name === 'g'
? {
...simplify(node.children[0]),
attributes: { // Merge attributes of the two nodes that merge into one
...node.attributes,
...node.children[0].attributes
}
}
: {
...node,
children: node.children.map(simplify)
};
}
// Sample input:
let root = {
"name": "svg",
"type": "element",
"value": "",
"attributes": {
"xmlns": "http://www.w3.org/2000/svg",
"width": "1440",
"height": "1080"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"fill": "#627580"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}, {
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}]
}]
}]
}]
};
root = simplify(root);
console.log(root);
您可以 运行 结构的基本遍历,但是,如果您遇到具有单个 g
标签 child 的 g
标签,只需调用 merge
那个 child:
var d = {'name': 'svg', 'type': 'element', 'value': '', 'attributes': {'xmlns': 'http://www.w3.org/2000/svg', 'width': '1440', 'height': '1080'}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {'fill': '#627580'}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {'stroke-linejoin': 'round'}, 'children': [{'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}]}, {'name': 'g', 'type': 'element', 'value': '', 'attributes': {'stroke-linejoin': 'round'}, 'children': [{'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}]}]}]}]}]}
function merge(d){
if (d.name != 'g' || d.children.length > 1 || d.children[0].name != 'g'){
return {...d, 'children':d.children.map(merge)}
}
return merge(d.children[0])
}
console.log(merge(d))
给定以下树:
{
"name": "svg",
"type": "element",
"value": "",
"attributes": {
"xmlns": "http://www.w3.org/2000/svg",
"width": "1440",
"height": "1080"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"fill": "#627580"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}, {
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}]
}]
}]
}]
}
...这是 HTML:
的表示<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1080">
<g>
<g>
<g fill="#627580">
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
</g>
</g>
</g>
</svg>
我如何在 JavaScript 中递归地转换此数据结构,以便所有只有一个 child <g>
的组 <g>
被折叠并且它们的 child ren 被分配到其 parent?
预期结果是这样的:
{
"name": "svg",
"type": "element",
"value": "",
"attributes": {
"xmlns": "http://www.w3.org/2000/svg",
"width": "1440",
"height": "1080"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}, {
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}]
}]
}
...这是 HTML:
的表示<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1080">
<g>
<g fill="#627580">
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
<g stroke-linejoin="round">
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
<path d="M150 0 L75 200 L225 200 Z" />
</g>
</g>
</g>
</svg>
理想情况下,不应有一个 <g>
元素与单个 child <g>
剩余。换句话说:
<g>
<g>
...
</g>
</g>
将转化为
<g>
...
</g>
这是我的尝试:
const collapseGroups = node => {
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
collapseGroups(child)
})
if (node.name == 'g' &&
node.children.length == 1 &&
node.children[0].name == 'g') {
node.children = node.children[0].children;
}
}
}
注意:我输入的是一个SVG文件,已经自动解析成上面提到的JS object.
您可以在每个节点上使用递归函数。如果它检测到它是“g”类型,并且只有一个子节点,则该节点吸收该子节点,并合并属性 属性:
function simplify(node) {
return node.name === 'g' && node.children.length === 1
&& node.children[0].name === 'g'
? {
...simplify(node.children[0]),
attributes: { // Merge attributes of the two nodes that merge into one
...node.attributes,
...node.children[0].attributes
}
}
: {
...node,
children: node.children.map(simplify)
};
}
// Sample input:
let root = {
"name": "svg",
"type": "element",
"value": "",
"attributes": {
"xmlns": "http://www.w3.org/2000/svg",
"width": "1440",
"height": "1080"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"fill": "#627580"
},
"children": [{
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}, {
"name": "g",
"type": "element",
"value": "",
"attributes": {
"stroke-linejoin": "round"
},
"children": [{
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}, {
"name": "path",
"type": "element",
"value": "",
"attributes": {
"d": "M150 0 L75 200 L225 200 Z"
},
"children": []
}]
}]
}]
}]
}]
};
root = simplify(root);
console.log(root);
您可以 运行 结构的基本遍历,但是,如果您遇到具有单个 g
标签 child 的 g
标签,只需调用 merge
那个 child:
var d = {'name': 'svg', 'type': 'element', 'value': '', 'attributes': {'xmlns': 'http://www.w3.org/2000/svg', 'width': '1440', 'height': '1080'}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {'fill': '#627580'}, 'children': [{'name': 'g', 'type': 'element', 'value': '', 'attributes': {'stroke-linejoin': 'round'}, 'children': [{'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}]}, {'name': 'g', 'type': 'element', 'value': '', 'attributes': {'stroke-linejoin': 'round'}, 'children': [{'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}, {'name': 'path', 'type': 'element', 'value': '', 'attributes': {'d': 'M150 0 L75 200 L225 200 Z'}, 'children': []}]}]}]}]}]}
function merge(d){
if (d.name != 'g' || d.children.length > 1 || d.children[0].name != 'g'){
return {...d, 'children':d.children.map(merge)}
}
return merge(d.children[0])
}
console.log(merge(d))