Javascript - 你可以在递归期间使用.shift()来改变数组吗?

时间:2016-03-09 04:21:21

标签: javascript arrays recursion

我编写了一个递归函数来确定数组是否包含要添加的必要元素并形成目标数字。虽然这样做,但我在尝试使用.shift()(第8行)删除数组中的第一个元素时遇到错误:

function findCombo(collection, target){
  if(target === 0){
   return true; 
  } else if(collection.length === 0){
   return false; 
  } else{
    var next = collection[0];
    //collection.shift(); **does not work**
    collection = collection.slice(1); //**works**
    return findCombo(collection, target - next) 
           || findCombo(collection, target);
  }
}

当我意识到collection.shift()是问题时,我尝试将数组更改为collection.slice(1),程序现在可以工作了。即使是现在,虽然我不明白为什么.shift()没有应用所需的结果。有谁知道为什么?

2 个答案:

答案 0 :(得分:1)

因为shift()修改了原始集合对象,所以当findCombo(collection, target)方法在findCombo(collection, target - next)之后执行时,集合对象将为空。



function findCombo(collection, target) {
  snippet.log(target + ':' + collection)
  if (target === 0) {
    return true;
  } else if (collection.length === 0) {
    return false;
  } else {
    var next = collection[0];
    collection.shift(); //**does not work**
    //collection = collection.slice(1); //**works**
    return findCombo(collection, target - next) || findCombo(collection, target);
  }
}
snippet.log(findCombo([1, 2, 3, 4, 5], 20));

<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

问题在于,您只有一个collection数组被findCombo的所有调用共享,并且shift会改变数组。这意味着当第一个递归调用findCombo(collection, target - next)清空数组时,第二个递归调用findCombo(collection, target)会发现(非常相同)数组为空,尽管调用者不打算这样做。通过使用slice,该函数不会损害给定的数组。

通过在递归调用之后将数组恢复为原始值,可以避免此问题:

var next = collection[0];
collection.shift();
var res = findCombo(collection, target - next) || findCombo(collection, target);
collection.unshift(next);
return res;

但这有点难看。更好的想法是为下一个要尝试的位置使用额外的索引参数,而不是根本不改变或克隆数组:

var next = collection[try];
return findCombo(collection, target - next, try+1) || findCombo(collection, target, try+1);