Looping into nested arrays - javascript

I am going through an exercise that asks me to remove the arrays that have elements that match with another variable.
e.g.
filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18)
should return [[10, 8, 3], [14, 6, 23]]
Given the fact that we are working with nested arrays I though about using a double for to loop into each element.
Like this:
function filteredArray(arr, elem) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] != elem) {
newArr.push(arr[i]);
}
}
// change code above this line
return newArr;
}
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
The expected result was to have an empty array, but it gives me:
[3, 2, 3]
The right solution is as follow:
function filteredArray(arr, elem) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(elem) == -1) { //Checks every parameter for the element and if is NOT there continues the code
newArr.push(arr[i]); //Inserts the element of the array in the new filtered array
};
};
return newArr;
};
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
Which makes sense, but I do not understand why mine is wrong.

Your issue is with:
if (arr[i][j] != elem) {
newArr.push(arr[i]);
}
You're pushing your array into newArr each time an inner element (newArr[i][j]) doesn't equal the filter element (elem). Instead, you want to push it into newArr if all the items in arr[i] are not equal to the elem. You could do this a few ways, one way would be to use a variable found which acts as a flag indicating whether the elem was found in any of the inner lists, and then add it if it was not found:
function filteredArray(arr, elem) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
let found = false;
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] == elem) {
found = true;
}
}
if(!found) {
newArr.push(arr[i]);
}
}
// move return out of for loop
return newArr; // change code above this line
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26],
[19, 3, 9]], 3));

You are getting [3, 2, 3] because you are returning from inside the first for loop. So, it only ever checks the first inner array. Even if you move it outside, the entire 2d array will be returned because every inner array has an element which will fail arr[i][j] == elem condition.
Alternatively, you could use filter and includes like this:
function filteredArray(arr, elem) {
return arr.filter(a => !a.includes(elem))
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

You check every element of the subarray, and if that does not match elem you push the subarray to the result. That means for [3, 18, 6] in your first example, it will check 3 against elem (18), then push that array, check 18 against elem, which won't fullfill the condition, then it will check 6 against 18 which does match again, the array gets pushed again. Instead you should check the whole array against the value, then push.
outer: for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] == elem) {
continue outer; // if one matches, exit the inner loop
}
// all checked, push
newArr.push(arr[i]);
}
}

There some wrong things in your code:
You let return in for loop.
You check every element in every sub array and push to result array when having the difference
I edit your code as below:
function filteredArray(arr, elem) {
let newArr = [];
for (let i = 0; i < arr.length; i++) { var check = false;
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] == elem) {
check = true;
}
}
} // change code above this line
return newArr;
}

Related

Algorithm problem with array subsequences [duplicate]

I am trying to write a function that will take an array and n as parameters,
it will return all subsets of that array with n elements, have tried a couple things, couldn't yet succeed.
thanks to whoever put it here, this functions is way too complicated and doesn't do the job, basically what I tried to do here is to pick out one element from a 4 element array to create its 3 element subsets. It doesn't even take N as parameter. it returns all 3 element subsets but also identical ones, so I have to filter them out as well, in any case I will keep trying.
function findSubsets(array) {
var answers = [];
var firstArray = array;
for (i = 0; i < array.length; i++) {
array = firstArray;
for (var k = 0; k < array.length; k++) {
if (k != i) {
var subset = array.splice(k, 1);
answers.push(array); array.splice(k, 0, subset[0]);
}
}
}
}
That not as complicated as it seems. This one is optimized because it doesn't creates useless temporary arrays during the process.
function findSubsets(array, n) {
var answers = [];
for(var i = 0 ; i < array.length ; i += n) {
answers.push(array.slice(i, i + n));
}
return answers;
}
findSubsets([1, 2, 3, 4, 5, 6, 7, 8, 9], 2) // --> [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
findSubsets([1, 2, 3, 4, 5, 6, 7, 8, 9], 3) // --> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
You can try this solution
var subsetArray = (function() {
return {
getResult: getResult
}
function getResult(array, n) {
function isBigEnough(value) {
return value.length === n;
}
var ps = [
[]
];
for (var i = 0; i < array.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(array[i]));
}
}
return ps.filter(isBigEnough);
}
})();
var arr = [1, 2, 3, 4,5,6,7,8,9];
console.log(subsetArray.getResult(arr,2));

Why is the variable i in the splice function decremented?

function filteredArray(arr, elem) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] === elem) {
arr.splice(i--, 1);
newArr = arr;
break;
}
}
}
return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
I have defined a function, filteredArray, which takes arr, a nested array, and elem as arguments, and returns a new array. elem represents an element that may or may not be present on one or more of the arrays nested within arr. Modify the function, using a for loop, to return a filtered version of the passed array such that any array nested within arr containing elem has been removed.
The expected output is [] (an empty array).
Question: Why is the variable i in the splice function decremented?
Because splice updates the original array in place. And in the for loop the condition to check if i < arr.length is calculated on every iteration.
Lets say you have an array of 10 items. In the first iteration arr.length will be 10. After that if you splice and remove 1 item from the array and then try to console.log(arr.length) you will see the length is updated to 9.
If you want to remove all the item in the sub array that is equal to the elem you can do that,
function filteredArray(arr, elem) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] === elem) {
arr[i].splice(j, 1);
}
}
newArr.push([...arr[i]])
}
return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

Why should we decrement an i variable and use break in a function?

What is the purpose of decrementing the "i" variable and using "break" in this function?
function filteredArray(arr, elem){
let newArr = [...arr];
for(let i = 0; i < newArr.length; i++){
for(let j = 0; j < newArr[i].length; j++){
if(newArr[i][j] === elem){
newArr.splice(i, 1);
i--;
break;
}
}
}
return newArr;
}
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
This is because by using newArr.splice(i, 1); you are removing the current index item from the array, so since all indexes will be moved by -1 for all elements following i at each splice, you then have to reduce i by 1, so you dont skip elements

Multidimensional array returns several undefined values upon iterating in javascript

I have a multidimensional array that returns undefined after the last value of every sub-array. Here is my code:
var bigArray = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
];
for (i = 0; i < bigArray.length; i++) {
for (j = 0; j <= bigArray[i].length; j++) {
console.log(bigArray[i][j]);
}
}
Remove the = part from the condition of the second loop. You tries to access an element out of the range of the array. Also declare your variables with var, let or const - in the case with i and j.
var bigArray = [
[1,2,3],
[4,5,6],
[7,8,9],
[10,11,12]
];
for(var i = 0; i < bigArray.length; i++) {
for(var j = 0; j < bigArray[i].length; j++) {
console.log(bigArray[i][j]);
}
}
In this case, '.length' method will return the total number elements in that array, But array index starts from 0. So if an array contains n elements the array index of the last element will be n-1. And if you are trying to access an array with index n it will return an ArrayIndexOutOfBound Exception.
You can try this code
var bigArray = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
];
for (i = 0; i <= bigArray.length-1; i++) {
for (j = 0; j <= bigArray[i].length-1; j++) {
console.log(bigArray[i][j]);
}
}

Chunk Array into groups - what's wrong with my code?

Below is the code :
function chunkArrayInGroups(arr, size) {
// Break it up.
var newArr =[];
for(var i = 0;i < arr.length;i++){
for(var j = 0;j < size;j++){
newArr.push(arr.splice(0,size));
}
}
var result = [];
for(i = 0;i < newArr.length;i++){
if(newArr[i].length != 0){
result.push(newArr[i]);
}
}
return result;
}
chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7,8], 2);
This should return - [[0, 1], [2, 3], [4, 5], [6, 7], [8]]. However, the code returns [[0, 1], [2, 3], [4, 5], [6, 7]]. Also, if my input array is ([0,1,2,3,4,5,6,7,8,9,10],2) my code returns as expected.
P.S: I am specifically looking to find what's wrong with this code instead of a different code/approach altogether.
Basically you need just one loop, because you splice the array and take a chunk of the wanted size of it.
This behaviour could be used to loop until the array has a length of zero and exit the loop.
In this case the result is ready.
function chunkArrayInGroups(arr, size) {
var newArr = [];
// for (var i = 0; i < arr.length; i++) {
while (arr.length) { // add this for looping and checking
// for (var j = 0; j < size; j++) {
newArr.push(arr.splice(0, size)); // keep this for doing the work!
// }
}
// var result = [];
// for (i = 0; i < newArr.length; i++) {
// if (newArr[i].length != 0) {
// result.push(newArr[i]);
// }
// }
// return result;
return newArr; // return only newArray
}
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can just do the following:
var size = 2;
var arr = [0,1,2,3,4,5,6,7,8];
var newArray = [];
for(var i = 0; i < arr.length; i+=size){
newArray.push(arr.slice(i,i+size))
}
console.log(newArray); //will output [[0,1],[2,3],[4,5],[6,7],[8]]
Your problem is that you are not treating the case where the remaining in the array is less than the given size, in other words the case when arr.length < size, so the remaining items in the array won't be taken into account in the chunk array.
You need to test upon it, I updated your code so it works perfectly:
function chunkArrayInGroups(arr, size) {
// Break it up.
var newArr =[];
while(size<arr.length){
newArr.push(arr.splice(0, size ));
}
if(arr.length<size){
newArr.push(arr);
}
}
Demo:
function chunkArrayInGroups(arr, size) {
// Break it up.
var newArr =[];
while(size<arr.length){
newArr.push(arr.splice(0, size));
}
if(arr.length<size){
newArr.push(arr);
}
return newArr;
}
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7,8], 2));
Note:
There's no need for using the result array as it's just a copy of the newArr, you could just return newArr without copying it.

Categories