How does a recursive call work in the function? - javascript

The purpose of this algorithm is to return an array which is split into smaller two-dimensional arrays inside of it. The length of each internal array is defined by size.
How does the recursive call with .slice() method work here?
How does it make the function return an array split into smaller sub-arrays?
I can't understand this solution.
function chunkyArrayInGroups(arr, size){
if(arr.length <= size){
return [arr];
} else {
return [arr.slice(0, size)].concat(chunkyArrayInGroups(arr.slice(size), size));
}
}

When going up the callstack, chunks get sliced away from the arrays front (.slice(size)):
[0, 1, 2, 3, 4, 5] -> [2, 3, 4, 5] -> [4, 5] -> []
Now at every recursive call there exists an intermediate value holding the sliced away part (.slice(0, size)):
[0, 1] [2, 3] [4, 5]
Now the chunked away parts get concatenated together when the stack unwinds:
[0, 1] [2, 3] [[4, 5]]
[0, 1] [[2, 3], [4, 5]]
[[0, 1], [2, 3], [4, 5]]

Related

How to get the length of all non-nested items in nested arrays?

The .length property on an array will return the number of elements in the array. For example, the array below contains 2 elements:
[1, [2, 3]] // 2 elements, number 1 and array [2, 3]
Suppose we instead wanted to know the total number of non-nested items in the nested array. In the above case, [1, [2, 3]] contains 3 non-nested items, 1, 2 and 3.
Examples
getLength([1, [2, 3]]) ➞ 3
getLength([1, [2, [3, 4]]]) ➞ 4
getLength([1, [2, [3, [4, [5, 6]]]]]) ➞ 6
You can flatten the array using .flat(Infinity) and then get the length. Using .flat() with an argument of Infinity will concatenate all the elements from the nested array into the one outer array, allowing you to count the number of elements:
const getLength = arr => arr.flat(Infinity).length;
console.log(getLength([1, [2, 3]])) // ➞ 3
console.log(getLength([1, [2, [3, 4]]])) // ➞ 4
console.log(getLength([1, [2, [3, [4, [5, 6]]]]])) // ➞ 6
You can use reduce on each array it'll find like this :
function getLength(arr){
return arr.reduce(function fn(acc, item) {
if(Array.isArray(item)) return item.reduce(fn);
return acc + 1;
}, 0);
}
console.log(getLength([1, [2, 3]]))
console.log(getLength([1, [2, [3, 4]]]))
console.log(getLength([1, [2, [3, [4, [5, 6]]]]]))
Recursively count the elements that you don't recurse into:
function getLength(a) {
let count = 0;
for (const value of a) {
if (Array.isArray(value)) {
// Recurse
count += getLength(value);
} else {
// Count
++count;
}
}
return count;
}
Live Example:
function getLength(a) {
let count = 0;
for (const value of a) {
if (Array.isArray(value)) {
count += getLength(value);
} else {
++count;
}
}
return count;
}
console.log(getLength([1, [2, 3]]));
console.log(getLength([1, [2, [3, 4]]]));
console.log(getLength([1, [2, [3, [4, [5, 6]]]]]));
You could just add the lengths for nested array or one.
function getLength(array) {
let count = 0;
for (const item of array) count += !Array.isArray(item) || getLength(item);
return count;
}
console.log(getLength([1, [2, 3]]));
console.log(getLength([1, [2, [3, 4]]]));
console.log(getLength([1, [2, [3, [4, [5, 6]]]]]));

Sorting an array of arrays of integers

I have a variable dimensions, which contains the maximum size of each element of an array, e.g.:
const dimensions = [10, 6, 4]
I also have an array of arrays containing as many integers as the size of the dimensions array, e.g.:
let boxes = [
[1, 2, 1],
[10, 2, 4],
[4, 1, 1],
[10, 2, 3]
]
For every array in boxes, no element will be higher than its counterpart in dimensions.
I want to find a way to sort these arrays, so that the sorted array boxes would be:
[
[1, 2, 1],
[4, 1, 1],
[10, 2, 3],
[10, 2, 4]
]
As you see, it's not just about sorting by the array's first element. It's sorting by first element, and if they're equal, the second, etc.
For each array of arrays, I have a related dimensions variable. But dimensions can be anything (also any length!) (and consequently, the arrays will have the same length of course).
I'm doing this in Javascript, but pseudocode is welcome too.
PS - This is not part of an assignment, I tried to abstract away most of the unnecessary stuff.
You can sort the values using Array.reduce to compare the values in each array being sorted, only updating the comparison result if it is currently 0 (i.e. the values up to now have been equal):
let boxes = [
[1, 2, 1],
[10, 2, 4],
[4, 1, 1],
[10, 2, 3]
]
boxes.sort((a, b) => a.reduce((c, v, i) => c ? c : v - b[i], 0));
console.log(boxes);

Javascript a var in closure always contain the same element?

See the fiddle here JSFIDDLE
var combine = function(n, k) {
function backtracking(n, k) {
if(k){ // min(k)=1, when k=0 break
for(var i=1; i<=n; ++i){
if(!used[i]){
used[i] = true;
solution[k-1] = i; // solution.length=k
// console.log(solution.length);
arguments.callee(n, k-1);
used[i] = false;
}
}
}else{
console.log(solution);
return result.push(solution); // ?
}
}
var used = [],
result = [],
solution = [];
if(k>n){
return [];
}else{
backtracking(n, k);
}
return result;
};
var b = combine(4, 2);
console.log(b);
why the result array always contain the same element>I mean it should have the same value like the array solution?
b output:
[[3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4]]
I expected this:
[[2, 1], [3, 1], [4, 1], [1, 2], [3, 2], [4, 2], [1, 3], [2, 3], [4, 3], [1, 4], [2, 4], [3, 4]]
I guess it's a closure problem .but how could I do this???
I try to make the result[] as a global var.but still not work..
I see that post. but it's closure within a loop. but this is not caused by loop problem .loop actually works fine.It's a recursive problem within a closure..
When you call:
return result.push(solution);
You're still using the same Array object again, any later change to that object will be persisted on the result.
You need to make a clone of the solution object each time you push it to result:
return result.push(solution.slice(0));
Here is the new Fiddle: Fiddle.

Compare arrays of different sizes and dimensions

So here's the proposed problem.
Compare two arrays and return a new array with any items not found in both of the original arrays.
Here's what I have so far.
function diff(arr1, arr2) {
for (var a in arr1) {
for (var b in arr2) {
if (arr1[a] == arr2[b]){
arr2.splice(b,1);
}
}
}
return arr2;
}
diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
This code basically just compares each value of the first array with the second one. If a match is found it then removes the item using the splice function.
This works great for arrays that are one dimensional but how can I get it to work for multidimensional arrays such as:
diff([1, 2, 3, 5], [1, [2, 3], [4, 5]]);
What if these arrays are not just two dimensions but any number of dimensions. I should be able to iterate through every element of every array no matter they are set up.
With lodash you can do this :
var a = [1, 2, 3, 5, 7], b = [1, [2, 3], [4, 5, [7]]];
var result = _.filter(_.flattenDeep(b), function(item){
return a.indexOf(item) === -1;
});
console.log(result);
$("body").append(JSON.stringify(result))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js"></script>
<body></body>

Is there a function to find subarray in javascript with repeated elements?

I am now writing a javascript to filter out arrays that contains a specific sub-array. Of course I can write the function by myself, but I am just curious if there are already some built-in function in javascript or other javascript library to do that, or if there are easy way to do that with just a few lines.
I found that I can use underscore.js if all the elements in the sub-array is unique. There is a intersection function and I can check the lenght after intersection to see if the length are correct. However, that function fails if there are repeated values in the sub-array.
For example,
_.intersection([1, 2, 3, 4, 5], [2, 1]);
This will return [1, 2] and by checking the length I will know this array contains the sub-array.
However, when there are repeated values in the sub-array,
_.intersection([1, 1, 2, 3, 4, 7, 10], [1, 1, 2]);
_.intersection([1, 2, 3, 4], [1, 1, 2]);
Both will return [1, 2] and the cases cannot be distinguished.
Is there other pre-built function I can use or is there a easy way to do the job within a few lines?
Try this:
function contains(a, b) {
// sort arguments
if(a.length < b.length) {
var temp = a;
a = b;
b = temp;
}
// copy array
a = a.slice();
return b.every(function(elm) {
var index = a.indexOf(elm);
if(index !== -1) {
// remove the found element
a.splice(index, 1);
return true;
}
return false;
});
}
console.log(contains([1, 1, 2], [1, 2, 3, 4, 7, 10])); // logs false
console.log(contains([1, 1, 2], [1, 1, 2, 3, 4, 7, 10])); // logs true
console.log(contains([1, 2, 3, 4, 7, 10], [1, 1, 2])); // logs false
console.log(contains([1, 1, 2, 3, 4, 7, 10], [1, 1, 2])); // logs true
Here is the demo

Categories

Resources