微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何删除树中的单个孩子?

如何解决如何删除树中的单个孩子?

给定以下树:

{
  "name": "svg","type": "element","value": "","attributes": {
    "xmlns": "http://www.w3.org/2000/svg","width": "1440","height": "1080"
  },"children": [{
    "name": "g","attributes": {},"children": [{
      "name": "g","children": [{
        "name": "g","attributes": {
          "fill": "#627580"
        },"children": [{
          "name": "g","attributes": {
            "stroke-linejoin": "round"
          },"children": [{
            "name": "path","attributes": {
              "d": "M150 0 L75 200 L225 200 Z"
            },"children": []
          },{
            "name": "path","children": []
          }]
        },{
          "name": "g","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 中递归地转换此数据结构,以便折叠所有只有一个子项 <g> 的组 <g>,并将其子项分配给其父项?

预期结果如下:

{
  "name": "svg","attributes": {
        "stroke-linejoin": "round"
      },"children": [{
        "name": "path","attributes": {
          "d": "M150 0 L75 200 L225 200 Z"
        },"children": []
      },{
        "name": "path","children": []
      }]
    },{
      "name": "g","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> 元素与单个子元素 <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对象了。

解决方法

您可以在每个节点上使用递归函数。如果它检测到它是“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","attributes": {},"children": [{
      "name": "g","children": [{
        "name": "g","attributes": {
          "fill": "#627580"
        },"children": [{
          "name": "g","attributes": {
            "stroke-linejoin": "round"
          },"children": [{
            "name": "path","attributes": {
              "d": "M150 0 L75 200 L225 200 Z"
            },"children": []
          },{
            "name": "path","children": []
          }]
        },{
          "name": "g","children": []
          }]
        }]
      }]
    }]
  }]
};

root = simplify(root);

console.log(root);

,

您可以运行结构的基本遍历,但是,如果您遇到具有单个 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','attributes': {},'attributes': {'fill': '#627580'},'attributes': {'stroke-linejoin': 'round'},'children': [{'name': 'path','attributes': {'d': 'M150 0 L75 200 L225 200 Z'},'children': []},{'name': 'path','children': []}]},{'name': 'g','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))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。