单元格面积大优先合并问题

稿件来源: 阳光企业网站管理系统   撰稿作者: 太阳光   发表日期: 2019-04-09   阅读次数: 116   查看权限: 游客查看

Q群里有人提问一个表格面积优先合并算法,考虑了良久才写了出来。

假如有这么个数组:

    var arr = [
        [1,1,1,2,2,2,2],
        [1,1,1,2,2,1,1],
        [1,3,1,1,1,2,2],
        [1,3,1,2,2,1,1],
        [1,3,1,2,1,1,1],
        [1,1,1,2,2,2,2]
    ]

把它绘成表格,然后合并相同单元格,并按面积最大优先合并。

开始想到的方法是先取一个元素,然后循环所有元素,找出该元素能合并的最大面积并合并。并循环遍历一下即可,得到如下图:

但仔细一看右下角有问题,本来最后一行右边可以合并4个单元格的。其实这个面积优先计算它应该要全方位考虑,很多单元格是相互制约关系。

此算法应该优先取出最大面积来合并。方法就是前面的基础上循环遍历,即每次取一个最大面积来合并单元格。重点是合并完后需要重新计算各自能合并的最大面积,因为有些相关单元格可能被合并了。如此循环到最后就能绘制表格了。

<table border="1" style="width:400px">
    <thead></thead>
    <tbody></tbody>
</table>
<script type="text/javascript">
    var arr = [
        [1,1,1,2,2,2,2],
        [1,1,1,2,2,1,1],
        [1,3,1,1,1,2,2],
        [1,3,1,2,2,1,1],
        [1,3,1,2,1,1,1],
        [1,1,1,2,2,2,2]
    ]
    var arrMap = [] // 克隆数组
    var arrPlane = [] // 扁平数组
    arr.forEach((array,l)=>{
        let a = []
        array.forEach((v,i)=>{
            let o = {v,l,i,a:1,ml:1,mr:1}
            a.push(o)
            arrPlane.push(o)
        })
        arrMap.push(a)
    })
    // 循环遍历函数
    ;(function(){
        if(!arrPlane.length){
            const _array = []
            arrMap.forEach(line => {
                let _arr = ['<td>*</td>']
                line.forEach(item => {
                    if (item.a === 0) {
                        _arr.push(`<td align="center" ${item.ml > 1 ? ' rowspan="' + item.ml + '"' : ''}${item.mr > 1 ? ' colspan="' + item.mr + '"' : ''}>${item.v}</td>`)
                    }
                })
                _array.push(_arr.join(''))
            })
            document.querySelector('thead').innerHTML = '<tr><th>#</th>'+arr[0].map(()=>'<th>#</th>').join('')+'</tr>'
            document.querySelector('tbody').innerHTML = '<tr>'+_array.join('</tr><tr>')+'</tr>'
            return
        }
        const length = arrMap.length
        // 核心计算最大面积
        arrPlane.forEach(obj => {
            var maxLine = 0 // 最大行数
            var maxRow = 0 // 最大列数
            var maxLen = null; // 序号
            var line,group,i,_line,_row
            hook:
              for (line = obj.l; line < length; line++) {
                  group = arrMap[line] // 整行数据
                  maxLen = maxLen === null ? group.length : maxLen
                  for (i = obj.i; i < maxLen; i++) {
                      var _obj = group[i]
                      if (_obj.v !== obj.v || _obj.a < 1) {
                          if (i === obj.i) break hook
                          break
                      }
                  }
                  maxLen = i
                  _line = line - obj.l + 1
                  _row = i - obj.i
                  // > :相同面积下优先合并行, >= :相同面积下优先合并列
                  if (_line * _row >= maxLine * maxRow) {
                      maxLine = _line
                      maxRow = _row
                  }
              }
            obj.mr = maxRow
            obj.ml = maxLine
            obj.a = maxLine * maxRow // 得出能合并的最大面积
        })
        // 按面积大小排序
        arrPlane.sort((a, b) => a.a > b.a ? -1 : 1)
        // 取最大面积的元素、并处理需要合并的单元格
        let obj = arrPlane.shift()
        for (var line = obj.l; line < obj.l + obj.ml; line++) {
            var group = arrMap[line]
            for (var row = obj.i; row < obj.i + obj.mr; row++) {
                group[row].a = -1
            }
        }
        obj.a = 0
        // 过滤数组
        arrPlane = arrPlane.filter(obj => obj.a > 0)
        arguments.callee()
    }())
</script>

效果如下:

关键词: 单元格,合并,面积优先   编辑时间: 2019-04-09 11:53:58

  • 感到高兴

    0

    高兴
  • 感到支持

    0

    支持
  • 感到搞笑

    0

    搞笑
  • 感到不解

    0

    不解
  • 感到谎言

    0

    谎言
  • 感到枪稿

    0

    枪稿
  • 感到震惊

    0

    震惊
  • 感到无奈

    0

    无奈
  • 感到无聊

    0

    无聊
  • 感到反对

    0

    反对
  • 感到愤怒

    0

    愤怒
0%(0)
0%(0)
上一篇:dart删除旧版本缓存包
下一篇:没有下一条记录
共有0 条评论 发言请遵守【相关规定

网友评论

会员头像
发 表同步腾讯微博    验证码:  点击更新请先登陆
  • 暂无评论
关闭模块文章图片 article Pictrue
  • 我的妈妈爸爸
  • 基于koa2+mysql+vue2.0+Element阳光内容管理系统
  • 代码覆盖率工具 Istanbul 入门教程
  • 全栈工程师的武器——MEAN
  • 9款超炫的 CSS3 复选框(Checkbox)
  • 微信开发在线翻译功能
  • CSS3那些不为人知的高级属性
  • 给easyui的datebox添加清空事件
  • flash写字效果
  • kendoUI系列教程之DropDownList下拉菜单
  • kendoUI系列教程之datetimepicker日期时间选择
  • kendoUI系列教程之datepicker日期选择
  • kendoUI系列教程之combobox下拉列表框
  • kendoUI系列教程之colorpicker
  • kendoUI系列教程之calendar日历表
  • kendoUI系列教程之autocomplete自动补齐