JavaScript非递归深度优先搜索来比较,匹配和返回未知长度

时间:2018-03-21 23:54:58

标签: javascript arrays loops recursion depth-first-search

正如标题所说,我正在寻找一种非递归解决方案,它接受一个对象数组,每个对象都包含一个存储在名为" dataMap"并且可以是任何尺寸和长度。存储在数组中的对象有两个属性:dataMap(类型Array)和i(类型Number)。

我在Stack Overflow上找到并阅读了这篇文章的其他帖子,但并没有与它与我的问题有关。 Non-recursive depth first search algorithm

示例数据结构:

Array[
       {
          dataMap:[...N],
          i:0
       },
       {
          dataMap:[...N],
          i:0
       },
       ...N
]

假设(来自上文):

  • "阵列"是任何长度,在运行时未知
  • "数据地图"是任何长度,在运行时未知
  • "数据地图"每个索引中的数据类型是任意的,可以是任何数据类型(在我的例子中,我只使用数字来保持简单)

编辑附录1.0: 解决方案部署的目标环境是Internet Explorer 10和ECMASript 5.解决方案需要匹配所有对,即使它们被重复。在我原来的递归解决方案中,如果运行代码,您将看到每个匹配的对都打印出来,无论它是否重复。这是因为这些数组中的每一个都表示包含来自其他数据库的数据的数据集,当匹配时,我需要获取有关该行的一些其他信息并将其返回。这只是背景故事,但与问题或解决方案并不特别相关,因为我试图简化它以简化它。 结束编辑附录1.0:

我有一个递归解决方案,但在完成和测试后,它只能使用未注释的对象数量(或接近)。如果取消注释数组中的最后一个对象并运行该程序,则会出现堆栈溢出。我希望它适合阅读。

var a = 
[
    {
    dataMap:[1,75,7,8,4,2,4,5,6,5,4,34,5,67,7,74,6,3,6,78,8,2,4],
    i:0
  },
  {
    dataMap:[2,5,8,6,5,4,6,4,5,76,8,8],
    i:0
  },
  {
    dataMap:[1,75,7,8,4,2,4,5,6],
    i:0
  },
  /*{
    dataMap:[3,5,7,5,4,3,5,7,56,7,9,6,5,2,2,5],
    i:0
  }*/


];


(function foo(array,level,compare){

  compare[level] = array[level].dataMap[array[level].i];


  if(typeof array[level-1] === "undefined"){
    // First array
    if(array[level].i == array[level].dataMap.length-1){
      // were at the end of the first array;
      return;
    }else{
      level++;
      array[level].i = 0;
    }
  }else if(typeof array[level+1] === "undefined"){
    // last array
    if(array[level].i == array[level].dataMap.length-1){
      level--;
      //array[level].i++;
    }
    array[level].i++;
  }else{
    // somewhere in the middle
    if(array[level].i == array[level].dataMap.length-1){
      // if at the end
      if(array[level+1].i == array[level+1].dataMap.length-1){
        //if the array below me is at their end
        // go up
        level--;
        array[level].i++;
      }
    }else{
      level++;
      array[level].i = 0;
    }
  }

  var t = true;
  for(var z=0;z<compare.length;z++){
    if(typeof compare[z+1] !== "undefined" && t != false && compare[z] != compare[z+1]){
        t = false;
    }
  }
  if(t){
    console.log("FOUND ONE:" + JSON.stringify(compare));
  }
  foo(array,level,compare);

})(a,0,[]);

选择递归函数的原因是最终将返回来自比较的匹配结果以存储在通过自执行内联函数执行该代码的变量中。递归是我认为我需要的,但清楚地看到存在内存问题。

可以使用jQuery。我选择使用纯JS。

那么,有没有办法完成我的要求?我的想法是将其分解为函数但不会导致相同的内存问题?

1 个答案:

答案 0 :(得分:0)

这个解决方案可能不是最好的,但我尝试过并且有效。

&#13;
&#13;
var array = 
[
    {
    dataMap:[1,1,75,34,8,4,2,4,5,6,5,4,34,5,67,7,74,6,3,6,78,8,2,4,67],
    i:0
  },
  {
    dataMap:[1,2,5,8,6,5,4,6,4,5,76,8,7,67],
    i:0
  },
  {
    dataMap:[1,75,8,4,2,4,5,67,6],
    i:0
  },
  {
    dataMap:[11,3,5,7,5,54,3,5,7,67,56,7,9,6,5,2,2,5],
    i:0
  }


];

/**
* Save no duplicated data to compare after
* Set, allow us to add no duplicated data
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set 
*/
addNoDuplicated = ( ( array, noDuplicated ) => {
  
  array.map( ( item ) => {
    
    item.dataMap.map( (data) => {
      
      noDuplicated.add( data );
      
    });
    
  } )
  
} )

deepSearchAndPrint = ( array, noDuplicated, duplicatedItSelf, accumDuplicated ) => {
  
  addNoDuplicated( array, noDuplicated );
  
  for ( let elem of noDuplicated ) { 
    
    accumDuplicated[elem] = [ ];
        
    array.map( ( item , index) => {
      
      duplicatedItSelf[index] = [];
      
      item.dataMap.map( ( data ) => { 
        
        // avoid add duplicated
        if ( data === elem && duplicatedItSelf[index].indexOf(data) === -1 ) {
          
          duplicatedItSelf[index].push(data);
                    
          accumDuplicated[elem].push(data)
          
        }
        
      } )
      
    })
    
    /**
    * check if sizes are equal, if they are equal, is a valid case
    */
    if ( accumDuplicated[elem].length === array.length ) {
      
      console.log( accumDuplicated[elem] );
      
    }
    
  }
    
}

deepSearchAndPrint( array, new Set(), { }, { } );
&#13;
&#13;
&#13;

更新

另一个解决方案是使用普通循环函数和函数声明。

&#13;
&#13;
var array = 
[
    {
    dataMap:[1,1],
    i:0
  },
  {
    dataMap:[1,3],
    i:0
  }/*,
  {
    dataMap:[1,7],
    i:0
  },
  {
    dataMap:[3,1],
    i:0
  }*/


];

/**
* Save all no duplicated data contained into each dataMap array
* noDuplicated: [1, 3]
* This is going to help us to compare
*/
function addNoDuplicated( array, noDuplicated ) {
  
  for ( let item of array ) {
  
    
    for ( let data of item.dataMap ) {
      
      // if they are primitive data type we use indexOf to check exist
      if ( noDuplicated.indexOf( data ) === -1 ) {
        
        noDuplicated.push( data );
        
      }
      
    };
  }
  
}

function deepSearchAndPrint( array, noDuplicated, duplicatedItSelf, accumDuplicated ) {
  
  addNoDuplicated( array, noDuplicated );
  
  /**
  * start looping through noDuplicated data array
  */
  
  // you can use normal loop here if you want
  for ( let elem of noDuplicated ) { 
    
    /**
    * create an array to each no repeated element 
    * noDuplicated: [1, 3]
    * accumDuplicated[elem] => 1: [],3: [], .... 
    */
    accumDuplicated[elem] = [ ];
    
    const arraySize = array.length;
    
    /**
    * iterate through our original array data structure
    */
    for ( let index = 0; index < arraySize; index++ ) {
     
      duplicatedItSelf[index] = [];
      
      const dataSize = array[index].dataMap.length;
      
      /**
      * iterate through each dataMap array
      */
      for ( let indexData = 0; indexData < dataSize; indexData++ ) { 
      
        let data = array[index].dataMap[indexData];
        
        /** 
        * avoid add duplicated values into a same array(dataMap)
        * e.g 
        * dataMap:[1,1]
        * dataMap:[1,3]
        * duplicatedItSelf[0] = [1]
        * duplicatedItSelf[1] = [1,3]
        */
        if ( data === elem && duplicatedItSelf[index].indexOf(data) === -1 ) {
          
          duplicatedItSelf[index].push(data);
          /**
          * save into accumDuplicated array according to key of noDuplicated data array
          * accumDuplicated[1] = [1]
          * accumDuplicated[1] = [1, 1]
          */
          accumDuplicated[elem].push(data)
          // console.log(accumDuplicated); // uncomment to verify
        }
        
      }
      
    }
    /**
    * if accumDuplicated in its own key has the same length as the general array => << match >>
    * accumDuplicated[0] = [1, 1] =>  = 2
    * array              = [ {}, {} ] = 2 
    */
    if ( accumDuplicated[elem].length === array.length ) {
      
       console.log( accumDuplicated[elem] );
      
    }
    
  }
  
}

deepSearchAndPrint( array, [ ], { }, { } );
&#13;
&#13;
&#13;

我希望能帮到你:)。