递归函数无法读取对象属性

时间:2019-07-04 15:45:11

标签: javascript recursion linked-list

我做了一个将数组变成列表的函数,如下所示:

function arrayToList(array) {
  var result = null;
  for (var i = array.length; i >= 0; i--) {
    result = {
      value: array[i],
      rest: result
    }
  }
  return result
}
console.log(arrayToList([10, 20]))

然后我尝试制作一个递归函数,该函数需要一个列表和一个数字,并在列表中的给定位置返回一个元素

这是第一次尝试:

function arrayToList(array) {
  var result = null;
  for (var i = array.length; i >= 0; i--) {
    result = {
      value: array[i],
      rest: result
    }
  }
  return result
}
function nthRecur(list, index) {
  var counter = 0
  if (counter === index) {
    return list.value
  } else {
    counter++
    list = list.rest
    return nthRecur(list, index)
  }
}
console.log(nthRecur(arrayToList([10, 20, 30]), 1))

第二次尝试:

function arrayToList(array) {
  var result = null;
  for (var i = array.length; i >= 0; i--) {
    result = {
      value: array[i],
      rest: result
    }
  }
  return result
}
function nthRecur(list, index) {
  var counter = 0
  if (counter === index) {
    return list.value
  } else {
    list = list.rest
    return nthRecur(list, index - 1)
  }
}
console.log(nthRecur(arrayToList([10, 20, 30]), 1))

它奏效了。我不知道为什么有人可以解释吗?

3 个答案:

答案 0 :(得分:2)

您可以直接使用索引来缩短它。

function arrayToList(array) {
    var result = null,
        i = array.length;
    while (i--) {
        result = { value: array[i], rest: result };
    }
    return result;
}


function nthRecur(list, index) {
    return index
        ? nthRecur(list.rest, index - 1)
        : list.value;
}

var list = arrayToList([10, 20, 30]);
console.log(list);
console.log(nthRecur(list, 1));

答案 1 :(得分:1)

问题在于此counter是局部变量,并且在每个递归调用中将其设置为0。您需要创建一个包装函数,并在其中声明counter

var counter = 0;

function arrayToList(array)
{
    var result = null;
    for (var i = array.length; i >= 0; i--)
    {
        result = {
            value: array[i],
            rest: result
        }
    }
    return result
}

function nthRecur(list, index)
{
   let counter = 0;
   function helper(list){
      if(counter === index)
      {
        return list.value
      }
      else
      {
          counter++
          list = list.rest
          return helper(list)
      }
   }
   return helper(list);
   
}
console.log(nthRecur(arrayToList([10, 20, 30]), 1));

答案 2 :(得分:0)

要改进Nina Scholz's answer,您可以为每个递归添加其他检查,以防止超出范围的索引抛出错误:

text.js

如果您还想支持负索引,类似于slice()splice(),则需要另一个函数来获取列表的function arrayToList (array) { return array.reduceRight( (rest, value) => ({ value, rest }), null ); } function item (list, index) { return list ? index ? item(list.rest, index - 1) : list.value : undefined; } const list = arrayToList([10, 20, 30]); console.log(item(list, 0)); console.log(item(list, 1)); console.log(item(list, 2)); console.log(item(list, 3));,然后调整{{ 1}}的功能:

length

P.S。上面的item使用reduceRight()来简化实现。 function arrayToList (array) { return array.reduceRight( (rest, value) => ({ value, rest }), null ); } function length (list, index = 0) { return list ? length(list.rest, index + 1) : index; } function item (list, index) { return list ? index ? index > 0 || (index += length(list)) > 0 ? item(list.rest, index - 1) : index < 0 ? undefined : list.value : list.value : undefined; } const list = arrayToList([10, 20, 30]); console.log(item(list, 0)); console.log(item(list, 1)); console.log(item(list, 2)); console.log(item(list, 3)); console.log(item(list, -1)); console.log(item(list, -2)); console.log(item(list, -3)); console.log(item(list, -4));可以使用spread syntax和递归来简化其实现:

arrayToList()