数据自动分类器,分成2类

  

/*
  * 分类器*/
  class ArraySplit {

    constructor(getDis) {
      this.getDis=getDis;

    }
    //计算元素key的最大长度dis、最大长度对应的元素arr
    getMaxKey(key1,indexArr,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,sArr) {
      const rNum=0|Math.random()*indexArr.length;
      //找到对边的点
      let line=this.getMaxKey(indexArr[rNum],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,line.dis]
    }
    splitByIndex(indexArr,sArr){
      if(indexArr.length<10){return indexArr;}
      const getDis=this.getDis
      const line=this.getSplitLine(indexArr,sArr)
      const arr1=[]
      const arr2=[]
      const arr3=[]
      let isLeft=0
      let isRight=0
      indexArr.forEach(function (key) {
        const left=getDis(sArr[line[0]],sArr[key]);
        const right=getDis(sArr[line[1]],sArr[key]);

        if(left*2<line[2]){
          arr1.push(key)
          if(left*8>3*line[2]){
            arr3.push(key)
            isLeft=1
          }
        }else if(right*2<line[2]){
          arr2.push(key)
          if(right*8>3*line[2]){
            arr3.push(key)
            isRight=1
          }
        }else{
          arr3.push(key)
        }
      })
      const data=[arr1,arr2,arr3]
      if(arr1.length>100||isLeft){
        data[0]=this.splitByIndex(arr1,sArr)
      }
      if(arr2.length>100||isRight){
        data[1]=this.splitByIndex(arr2,sArr)
      }
      if(arr3.length>100||isLeft||isRight){
        data[2]=this.splitByIndex(arr3,sArr)
      }
      return {
        line,
        data
      }
    }
    //对数组分类,成2部分
    split(sArr){
      const indexArr=sArr.map(function (item,i) {
        return i;
      })
      return this.splitByIndex(indexArr,sArr)
    }
  }

  

  
  //分类器demo
  const sArr=[]
  for(let i=0;i<100;i++){
    sArr.push({x:0|Math.random()*1000,y:0|Math.random()*1000})
  }

  function getDis(key1,key2) {
    return Math.abs(key1.x-key2.x)+Math.abs(key1.y-key2.y);
  }

  const asplit=new ArraySplit(getDis)

  const tag=asplit.split(sArr)
  console.log(JSON.stringify(tag))

  

原文地址:https://www.cnblogs.com/caoke/p/14765268.html