Рекурсивная функция не может прочитать свойство объекта - PullRequest
1 голос
/ 04 июля 2019

Я сделал функцию, которая превращает массив в список, который выглядит так:

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 ]

2 голосов
/ 04 июля 2019

Вы можете сократить его, используя индекс напрямую.

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 голос
/ 04 июля 2019

Проблема в том, что 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));
0 голосов
/ 04 июля 2019

Чтобы улучшить Ответ Нины Шольц , вы можете добавить дополнительную проверку к каждой рекурсии, чтобы индексы из-за пределов не выдавали ошибку:

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));

Если вы хотите также поддерживать отрицательные индексы, аналогично slice() и splice(), вам потребуется другая функция для получения length списка и затем настройте функцию item соответственно:

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));

P.S. arrayToList() выше использует reduceRight() для упрощения реализации. listToArray() может использовать расширенный синтаксис и рекурсию для упрощения его реализации:

function arrayToList (array) {
  return array.reduceRight(
    (rest, value) => ({ value, rest }),
    null
  );
}

function listToArray (list, array = []) {
  return list
    ? listToArray(list.rest, [...array, list.value])
    : array;
}

const list = arrayToList([10, 20, 30]);
const array = listToArray(list);

console.log(list);
console.log(array);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...