The problem is that your recursive call does not pass the second argument.
Without passing it, each recursive call will just populate its own, new array. It does return that array to the caller, but the caller (making the recursive call) ignores that returned value, so all the work of the recursive call is for nothing.
So the easy fix is to change this:
} else {
recursion(nE);
to this:
} else {
recursion(nE, resultAry);
Answer from trincot on Stack OverflowThe problem is that your recursive call does not pass the second argument.
Without passing it, each recursive call will just populate its own, new array. It does return that array to the caller, but the caller (making the recursive call) ignores that returned value, so all the work of the recursive call is for nothing.
So the easy fix is to change this:
} else {
recursion(nE);
to this:
} else {
recursion(nE, resultAry);
Try this:
function recursion(array, resultAry = []) {
array.forEach((element) => {
if (typeof element === "string") {
console.log(element);
resultAry.push(element);
} else {
nE = rndmElementSelection(element);
if (typeof nE === "string") {
console.log(nE);
resultAry.push(nE);
} else {
resultAry = [...resultAry, ...recursion(nE)];
}
}
});
return resultAry;
}
Videos
The problem is how you are passing the processing of array, if the value is an array then you are keep calling it causing an infinite loop
function flatten() {
var flat = [];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] instanceof Array) {
flat.push.apply(flat, flatten.apply(this, arguments[i]));
} else {
flat.push(arguments[i]);
}
}
return flat;
}
Demo: Fiddle
Here's a more modern version:
function flatten(items) {
const flat = [];
items.forEach(item => {
if (Array.isArray(item)) {
flat.push(...flatten(item));
} else {
flat.push(item);
}
});
return flat;
}
The clean way to flatten an Array in 2019 with ES6 is flat()
Short Answer:
array.flat(Infinity)
Detailed Answer:
const array = [1, 1, [2, 2], [[3, [4], 3], 2]]
// All layers
array.flat(Infinity) // [1, 1, 2, 2, 3, 4, 3, 2]
// Varying depths
array.flat() // [1, 1, 2, 2, Array(3), 2]
array.flat(2) // [1, 1, 2, 2, 3, Array(1), 3, 2]
array.flat().flat() // [1, 1, 2, 2, 3, Array(1), 3, 2]
array.flat(3) // [1, 1, 2, 2, 3, 4, 3, 2]
array.flat().flat().flat() // [1, 1, 2, 2, 3, 4, 3, 2]
Mozilla Docs
Can I Use - 96% Oct '23
You are checking for the presence of key each time through the loop over the object's properties. So you are getting as many values as there are properties on the object. So:
function getValuesByKey(object, key) {
var values = [];
recursiveFx(object);
function recursiveFx(object) {
if (key in object) values.push(object[key]);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
for (var property in object) {
if (object.hasOwnProperty(property)) {
if (typeof object[property] == "object") {
recursiveFx(object[property]);
}
}
}
}
return values;
}
Alternative: use JSON.stringify with replacer
Anyway, you can do this more easily with
function getValuesByKey(object, key) {
var values = [];
JSON.stringify(object, function(k, v) {
if (k === key) values.push(v);
return v;
});
return values;
}
This uses the replacer parameter to JSON.stringify to intercept each key value pair. The stringified value itself we don't need and throw away.
Just an idea of recursion:
var data = { "children": [{ "id": "5", "parentid": "0", "text": "Device Guides", "index": "1", "children": [{ "id": "10", "index": "0", "text": "Grandstream GXP-21XX" }, { "id": "11", "index": "1", "text": "Polycom Soundstation/Soundpoint" }, { "id": "23", "parentid": "8", "index": "2", "text": "New Polycom", "children": [{ "id": "5", "parentid": "0", "text": "Device Guides", "index": "1", "children": [{ "id": "10", "index": "0", "text": "Grandstream GXP-21XX" }, { "id": "11", "index": "1", "text": "Polycom Soundstation/Soundpoint" }, { "id": "23", "index": "2", "text": "New Polycom" }] }, { "id": "6", "parentid": "0", "text": "Pre-Sales Evaluation", "index": "0", "children": [] }, { "id": "7", "parentid": "0", "text": "Router Setup Guides", "index": "2", "children": [{ "id": "9", "index": "0", "text": "Sonicwall" }, { "id": "12", "index": "1", "text": "Cisco" }] }] }, { "id": "6", "parentid": "0", "text": "Pre-Sales Evaluation", "index": "0", "children": [] }, { "id": "7", "parentid": "0", "text": "Router Setup Guides", "index": "2", "children": [{ "id": "9", "index": "0", "text": "Sonicwall" }, { "id": "12", "index": "1", "text": "Cisco" }] }] }] };
function getValuesByKey(object, key) {
var values = [];
function r(obj) {
Object.keys(obj).forEach(function (k) {
if (Array.isArray(obj[k])) {
obj[k].forEach(r);
return;
}
if (typeof obj[k] === 'object') {
r(obj[k]);
return;
}
k === key && !~values.indexOf(obj[k]) && values.push(obj[k]);
});
}
r(object);
return values;
}
document.write('<pre>' + JSON.stringify(getValuesByKey(data, 'id'), 0, 4) + '</pre>');
You're creating a new array instead of passing it to the recursive call.
Do this instead.
DEMO: http://jsfiddle.net/kDtZn/
function addToArray(array) {
array.push(prompt("Add items to array or 'q' to stop"));
if (array[array.length-1] == 'q') {
array.pop();
document.write(array)
}
else {
addToArray(array);
}
}
addToArray([]);
Now you start with an empty array, and for each recursive call, it passes the same array forward.
Also, I changed it so that it doesn't use .pop() in the if() condition, otherwise you'll always end up with an empty array when it comes time to write it. (The .pop() method actually removes the last item.)
Finally, make sure you're not using document.write after the DOM is loaded. If so, you need to change it to use DOM manipulation methods instead.
You could take a different approach so that you don't need .pop() at all.
DEMO: http://jsfiddle.net/kDtZn/1/
function addToArray(array) {
var item = prompt("Add items to array or 'q' to stop");
if (item == 'q') {
document.body.textContent = array;
} else {
array.push(item);
addToArray(array);
}
}
addToArray([]);
The reason your while loop didn't work is very likely because of the original .pop() issue.
Your function recreates var array = [] on every loop/recursion. I am not sure if recursion is the right tool for the job in your case - it does not seems like it - but if you're starting out with JavaScript/development and just trying it out then you're fine.