大数据数据结构-分类模型

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据分类器demo</title>
</head>
<body>
<button onclick="splitArr()">分类</button>
    <div id="app"></div>

</body>
<script>
  function getDis(key1,key2) {
    const x=Math.abs(key1.x-key2.x)
    const y=Math.abs(key1.y-key2.y)
    return Math.sqrt(x*x+y*y);
  }

  Array.prototype.pushOnly=function(one){
    if(this.indexOf(one)===-1){
      this.push(one)
    }
  }
  /*
  * 分类器*/
  class ArraySplit {

    constructor(getDis,sArr) {
      this.getDis=getDis;
      this.sArr=sArr;
      this.tagMap={};
      this.dataMap={};

      const indexArr=sArr.map(function (item,i) {
        return i;
      })
      this.splitByIndex(indexArr,'')
      console.log(this.tagMap)
      console.log(this.dataMap)
    }
    //计算元素key的最大长度dis、最大长度对应的元素arr
    getMaxKey(key1,indexArr) {
      const sArr=this.sArr
      const getDis=this.getDis
      let maxDis=0;
      let allDis=0;
      let arr=[]

      indexArr.forEach(function (key2) {
        const dis=getDis(sArr[key1],sArr[key2])
        allDis=allDis+dis;
        if(dis>maxDis){
          arr=[key2]
          maxDis=dis
        }else if(dis===maxDis){
          arr.push(key2)
        }
      })
      return {
        key:key1,
        dis:maxDis,
        allDis:allDis,
        arr
      }
    }

    //获取数据分割线(两个风格点)
    getSplitLine(indexArr) {
      const sArr=this.sArr
      //找到对边的点
      let line=this.getMaxKey(indexArr[0],indexArr,sArr)

      let isMax=false;
      let moreKey;
      let maxDis=0;
      while (!isMax){
        taskArr.push(line.key)
        isMax=true;
        maxDis=0;
        for(let i=0;i<line.arr.length;i++){
          const key=line.arr[i]
          if(key!==line.key){
            const m2=this.getMaxKey(key,indexArr,sArr)
            const dis=m2.allDis;
            if(m2.dis>line.dis||m2.dis===line.dis&&m2.arr.length>line.arr.length||m2.dis===line.dis&&m2.arr.length===line.arr.length&&m2.allDis>line.allDis){
              line=m2
              isMax=false;
              break
            }else if(dis>maxDis){
              maxDis=dis
              moreKey=key
            }
          }
        }
      }

      let lessKey=line.key;
      return [lessKey,moreKey,parseInt(line.dis)]
    }
    getTags(ele,line){
      const sArr=this.sArr
      const getDis=this.getDis
      const tags=[]
      const left=getDis(sArr[line[0]],ele);
      const right=getDis(sArr[line[1]],ele);
      if(left*2<line[2]){
        tags.push(0)
        if(left*8>3*line[2]){
          tags.push(2)
        }
      }else if(right*2<line[2]){
        tags.push(1)
        if(right*8>3*line[2]){
          tags.push(2)
        }
      }else{
        tags.push(2)
      }
      return tags;
    }

    splitByIndex(indexArr,deep){
      const sArr=this.sArr
      const line=this.getSplitLine(indexArr)
      const data=[[],[],[]]
      indexArr.forEach( (key) =>{
       const tags=this.getTags(sArr[key],line);
        tags.forEach(function (tag) {
          data[tag].push(key)
        })
      })
      data.forEach( (arr0,i)=> {
        const tag0=deep+String(i)
        if(arr0.length>2){
          this.splitByIndex(arr0,tag0)
        }else if(arr0.length){
          this.dataMap[tag0]=arr0;
        }
      })
      if(data[2].length===0){
        this.dataMap[deep]=indexArr
      }else{
        this.tagMap[deep]=line;
      }
    }

    getNearTags(ele){
      let t0Arr=['']
      let t1Arr=[]
      let lock=false;
      while (!lock){
        const cArr=[]
        t0Arr.forEach((path)=> {
          const line=this.tagMap[path]
          if(line){
            const tags=this.getTags(ele,line)
            tags.forEach(function (tag) {
              cArr.pushOnly(path+tag)
            })
          }else{
            t1Arr.pushOnly(path)
          }
        })
        if(cArr.length>0){
          t0Arr=cArr;
        }else{
          lock=true;
          t0Arr.forEach(function (path) {
            t1Arr.pushOnly(path)
          })
        }
      }
      return t1Arr.reverse();
    }
    //对数组分类,成2部分
    getNearEles(ele){
      const tags=this.getNearTags(ele)
      console.log(tags)
      const eles=[]
      tags.forEach((tag)=> {
        this.dataMap[tag].forEach((i)=>{
          eles.pushOnly(i)
        })
      })
      return eles
    }
  }


  let taskArr=[]

    const room=document.querySelector('#app')
    const arr=[]
    for(let i=0;i<500;i++){
      // const r=0|Math.random()*10+3
      const r=5
      const x=0|Math.random()*600
      const y=0|Math.random()*400
      arr.push({
        x,y,r
      })
    }
    const eleArr=[]
    arr.forEach(function ({x,y,r}) {
      const ele=document.createElement('div')
      ele.className='item'
      ele.style.top=(y-r/2)+'px'
      ele.style.left=(x-r/2)+'px'
      ele.style.width=r+'px'
      ele.style.height=r+'px'
      room.appendChild(ele)
      eleArr.push(ele)
    })
    const testArr=[{x: 92, y: 217, r: 2}]
  testArr.forEach(function ({x,y,r}) {
    const ele=document.createElement('div')
    ele.className='item test'
    ele.style.top=(y-r/2)+'px'
    ele.style.left=(x-r/2)+'px'
    ele.style.width=r+'px'
    ele.style.height=r+'px'
    room.appendChild(ele)
  })
  function sleep(time) {
    return new Promise(function (resolve) {
      setTimeout(resolve,time)
    })
  }
  let preTag;
  let running=false;
  async function splitArr(){
    if(running){return;}
    running=true;
    taskArr.forEach(function (num) {
      eleArr[num].classList.remove('task')
    })
    taskArr=[]
    if(preTag){
      eleArr[preTag.line[0]].classList.remove('top')
      eleArr[preTag.line[1]].classList.remove('bottom')
      preTag.data[0].forEach(function (num) {
        eleArr[num].classList.remove('top2')
      })
      preTag.data[1].forEach(function (num) {
        eleArr[num].classList.remove('bottom2')
      })
      preTag.data[2].forEach(function (num) {
        eleArr[num].classList.remove('middle2')
      })
      await sleep(1000)
    }

    const splitObj=new ArraySplit(getDis,arr)
    const tag1= splitObj.getNearEles(testArr[0])
    console.log(JSON.stringify(tag1))
    for(let i=0;i<tag1.length;i++){
      const num=tag1[i]
      eleArr[num].classList.add('task')
      await sleep(100)
    }
    return
    for(let i=0;i<taskArr.length;i++){
      const num=taskArr[i]
      eleArr[num].classList.add('task')
      await sleep(100)
    }
    preTag=tag1;
    eleArr[tag1.line[0]].classList.remove('task')
    eleArr[tag1.line[0]].classList.add('top')
    await sleep(100)
    eleArr[tag1.line[1]].classList.remove('task')
    eleArr[tag1.line[1]].classList.add('bottom')
    await sleep(100)
    for(let i=0;i<tag1.data[0].length;i++){
      const num=tag1.data[0][i]
      if(num!==tag1.line[0]&&taskArr.indexOf(num)===-1){
        eleArr[num].classList.add('top2')
      }
    }
    await sleep(1000)
    for(let i=0;i<tag1.data[1].length;i++){
      const num=tag1.data[1][i]
      if(num!==tag1.line[1]&&taskArr.indexOf(num)===-1){
        eleArr[num].classList.add('bottom2')
      }
    }
    await sleep(1000)
    for(let i=0;i<tag1.data[2].length;i++){
      const num=tag1.data[2][i]
      if(num!==tag1.line[1]&&taskArr.indexOf(num)===-1){
        eleArr[num].classList.add('middle2')
      }
    }
    running=false
  }

</script>
<style>
    #app{
        position: relative;
        border: 1px saddlebrown solid;
        width: 620px;
        height: 420px;
    }
    .item{
        position: absolute;
        left: 0;
        top: 0;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background: black;
    }
    .test{
        background: #f422ff;
    }
    .task{
        background: red;
    }
    .top{
        background: red;
    }
    .bottom{
        background: #121bff;
    }
    .top2{
        background: #7cff97;
    }
    .bottom2{
        background: #ffb148;
    }
    .middle2{
        background: #ff38d2;
    }
</style>
</html>

  

posted @ 2021-05-19 16:26  无工时代  阅读(112)  评论(0)    收藏  举报