#javascript #arrays #list #recursion
#javascript #массивы #Список #рекурсия
Вопрос:
Я новичок в javascript. У меня есть две функции: одна называется arrayToList, которая принимает массив и создает из него список, другая называется listToArray, которая принимает список и создает из него массив. первый работает нормально. Однако в случае второго я должен создать пустой массив только на первой итерации цикла for или while, в рамках которого я буду передавать каждое значение list в созданный мной массив и на каждом шаге удалять list.value и устанавливать для списка значение list.rest (то есть restсписка), а затем рекурсивно продолжать вызывать ту же функцию.
Моя проблема в том, что я не могу объявить массив внутри функции. Если я скажу if(!array) {let array=[];}
, то получу сообщение, что массив не определен, если я объявлю массив как глобальный, то он сохраняет значения при разных вызовах функции, чего я не хочу. Ниже приведен код. Спасибо за вашу помощь.
let array=[];
function listToArray(list) {
while(list.value) {
array.push(list.value);
delete list.value;
list=list.rest;
listToArray(list);
}
return array;
}
console.log(listToArray({value: 10, rest: {value: 20, rest: {
value: 30
rest: {value: 50, rest: {value: 70, …}}));
Ответ №1:
Вы могли бы использовать рекурсивный подход, не используя массив для сбора вложенных элементов.
function nestedObjToArray({ value, rest }) {
return [value, ...(rest ? nestedObjToArray(rest) : [])];
}
console.log(nestedObjToArray({ value: 10, rest: { value: 20, rest: { value: 30, rest: { value: 50, rest: { value: 70 } } } } }));
Комментарии:
1. Привет, Нина, спасибо за ответ. это работает, но я не хочу передавать предпочтительно второй параметр, я новичок, поэтому ваш код кажется мне немного сложным для понимания. в любом случае, спасибо за помощь, @CertainPerformance предоставил альтернативы вашему методу, которые немного легче понять. Я буду использовать ваш метод, когда я больше не буду новичком :), прямо сейчас это меня пугает.
2. @sb16: там есть только один параметр. Он просто деструктурирован, чтобы разрешить прямой доступ к его свойствам. Это эквивалентно
const listToArray = (x) => [x.value, ...(x.rest ? listToArray(x.rest) : [])]
Ответ №2:
Я бы использовал 2-й параметр по умолчанию, который по умолчанию равен пустому массиву, а затем передал его:
function nestedObjToArray(obj, arr = []) {
arr.push(obj.value);
if (obj.rest) {
nestedObjToArray(obj.rest, arr);
}
return arr;
}
console.log(nestedObjToArray({
value: 10,
rest: {
value: 20,
rest: {
value: 30,
rest: {
value: 50,
rest: {
value: 70,
}
}
}
}
}))
Таким образом, массив создается при первом вызове функции, потому что функция изначально не вызывается со вторым параметром. При последующих рекурсивных вызовах созданный массив передается в качестве второго параметра.
Обратите внимание, что «список» не имеет общепринятого универсального значения в JS. Некоторые могут подумать, что вы имеете в виду обычный массив. Поскольку то, что вы передаете, является вложенным объектом, вы можете вызвать функцию nestedObjToArray
или что-то подобное.
Если вы не можете передать другой параметр, вы можете создать массив при последнем рекурсивном вызове и вернуть его:
function nestedObjToArray(obj) {
const arr = obj.rest ? nestedObjToArray(obj.rest) : [];
arr.unshift(obj.value);
return arr;
};
console.log(nestedObjToArray({
value: 10,
rest: {
value: 20,
rest: {
value: 30,
rest: {
value: 50,
rest: {
value: 70,
}
}
}
}
}))
Комментарии:
1. Привет @CertainPerformance, спасибо за ответ. Ваш метод — хороший способ достижения желаемого эффекта, я также подумал о чем-то подобном тому, что вы написали, но мой вопрос в том, есть ли способ, которым мы можем это сделать, не передавая второй параметр? Если мы не передадим второй параметр при вызове метода, будет ли он автоматически создавать массив?
2. Вы можете создать массив при последнем рекурсивном вызове, но это более запутанно, IMO
3. хорошо, я забыл, как использовать параметры по умолчанию. спасибо за напоминание, ваш метод — это правильный путь. большое вам спасибо.