Voroba1996
@Voroba1996
JS разработчик

Циклы, рекурсия и массивы в JAVASCRIPT?

6246e56f7e895811234380.png
6246e55f36af6729542903.png

Есть задача, фото сверху, и есть некоторое решение (код снизу!) Вопрос для понимающих.. что можно исправить для хорошей читабельности и быстрой работы кода?

P.S. Задачки из книги "Выразительный JS"

function arrayToList(array){
    return {
        value: array[array.length - 1],
        rest: array.length - 1 === 0 ? null : arrayToList(array.slice(0, array.length - 1))
    }
}
function listToArray(object){
    let array = []
    while(object != null){
        array.push(object.value)
        object = object.rest
    }
    return array
}
function prepend(elem, list){
    let newList = listToArray(list)
    newList.push(elem)
    return arrayToList(newList)
}
function nth(object, index){
    let array = listToArray(object)
    return array[index]
}
  • Вопрос задан
  • 112 просмотров
Решения вопроса 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
arrayToList - а точно список должен формироваться в обратном порядке? Если да, то почему listToArray формирует в прямом?
listToArray(arrayToList([1, 2, 3])); // Array(3) [ 3, 2, 1 ]

Функция prepend работает неправильно, переворачивая исходный список.
const list = {
  value: 2,
  rest: {
    value: 3,
    rest: null,
  },
};
prepend(1, list);
/* 
Object {
  value: 1,
  rest: Object {
    value: 3,
    rest: Object {
      value: 2,
      rest: null
    }
  }
}
*/

Рекурсивные варианты

const arrayToList = (arr, idx = 0) => ({
  value: arr[idx],
  rest: idx === arr.length - 1
          ? null
          : arrayToList(arr, idx + 1)
});
const listToArray = (list) => (
  list.rest === null
    ? [list.value]
    : [list.value, ...listToArray(list.rest)]
);
const prepend = (value, rest) => ({ value, rest });
const nth = (list, idx) => (
  idx === 0
    ? list.value
    : (
      list.rest === null
        ? undefined
        : nth(list.rest, idx - 1)
    )
);


Нерекурсивные варианты

const arrayToList = (arr) => {
  const list = null;
  for (let i = arr.length - 1; idx >= 0; idx -= 1) {
    list = { value: arr[idx], rest: list };
  }
  return list;
};
const listToArray = (list) => {
  const arr = [];
  while (list !== null) {
    arr.push(list.value);
    list = list.rest;
  }
  return arr;
};
const prepend = (value, rest) => ({ value, rest });
const nth = (list, idx) => {
  while (list !== null) {
    if (idx === 0) {
      return list.value;
    }
    idx -= 1;
    list = list.rest;
  }
};

Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
dollar
@dollar
Делай добро и бросай его в воду.
Ничего, разве что ; расставить. Я бы ещё длинную строку кое-как разбил, но это вкусовшина. Ещё я бы писал arr вместо array, ибо в других языках это зарезервированное слово, да и в js есть Array (а также obj вместо object), но не уверен, что это улучшит читабельность именно для новичков.
Ответ написан
Комментировать
RAX7
@RAX7
Для читаемости можно вынести часто повторяющиеся выражения в переменную
function arrayToList(array) {
  const last = array.length - 1;
  return {
    value: array[last],
    rest: last === 0 ? null : arrayToList(array.slice(0, last))
  };
}

Для скорости - не использовать array.slice, т.к. копирование массива довольно дорого
function arrayToList(array, idx = array.length - 1) {
  return {
    value: array[idx],
    rest: idx === 0 ? null : arrayToList(array, idx - 1)
  };
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы