【问题标题】:How do I remove single children in a tree?如何删除树中的单身儿童?
【发布时间】:2021-08-21 21:15:37
【问题描述】:

给定以下树:

{
  "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 中递归地转换此数据结构,以便折叠只有一个子 &lt;g&gt; 的所有组 &lt;g&gt;,并将其子代分配给其父代?

预期的结果是这样的:

{
  "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>

理想情况下,&lt;g&gt; 元素不应与单个子元素 &lt;g&gt; 保持一致。换句话说:

<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 对象。

【问题讨论】:

  • 我会为此而绞尽脑汁,但你标题中问题的答案是“致电消防部门”。
  • 数据结构是什么?一个字符串?
  • @trincot 在问题中添加了额外信息
  • 我认为他 (@Miki) 想要这样的东西:[ [data] ] -> [data]
  • 好的,很清楚。已发布答案。

标签: javascript recursion data-structures recursive-datastructures


【解决方案1】:

您可以运行结构的基本遍历,但是,如果遇到具有单个 g 子标签的 g 标签,只需在该子标签上调用 merge

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))

【讨论】:

    【解决方案2】:

    您可以在每个节点上使用递归函数。如果它检测到它是“g”类型,并且只有一个孩子,则节点吸收孩子,同时合并 attributes 属性:

    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);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多