Array Destructuring with in a for of loop? - javascript

i'm trying to understand the following code? and why i get the following output
for (let [i, j, ...x] of [
[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5)
]) {
console.error(x)
}
expected output [10, 11, 12, 13] actual output x = [12, 13]

for(let [i, j, ...x] of [[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5 )]) {
console.error(x)
}
First you need to look at [2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5 )
which returns: [10, 11, 12, 13].
Afterwards [i, j, ...x] = [10, 11, 12, 13]will get applied. This means, i = 10, j = 11 and x takes the rest which means x = [12, 13].
We print x and voila, it's [12, 13].
But what about [[10, 11, 12, 13]]? First see the snippet below:
let [k, l, ...y] = [2, 3, 4, 5, 10, 11, 12, 13]
console.log(k,l,y)
let [i, j, ...x] = [[2, 3, 4, 5, 10, 11, 12, 13]]
console.log(i,j,x)
So with a single bracket we get the expected results so why in the given code we have double brackets and it works just fine?
Well, see the following snippet and compare:
for (let [i, j, ...x] of [[2, 3, 4, 5, 10, 11, 12, 13]]) {
console.log(i,j,x)
}
This works just fine but what happens when we loop with single brackets?
for (let [i, j, ...x] of [2, 3, 4, 5, 10, 11, 12, 13]) {
console.log(i,j,x)
}
We get an error! But why?
for...of gets us the inner values of the array of array via its internal iterator. It gets us the 'next' element from our outer array which is our inner array. That's why we only ever got a single iteration in our loop anyway since there is only one 'next'!
On that single element we are iterating we apply the deconstructing syntax and print the result. It's a lot of hot air over nothing, basically.

You Just need to remove i,j
for (let [...x] of [
[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5)
]) {
console.error(x)
}

if you want to get numbers that are larger than 5 , you can use this code
for (let [i, j, ...x] of [
[2, 3, 4, 5, 10, 11, 12, 13].filter(e => e > 5)
]) {
console.error(x)
}
var numberArray= [2, 3, 4, 5, 10, 11, 12, 13];
var numberBiggerThanFive = [];
for(i in numberArray){
if(i > 5 ){
numberBiggerThanFive.push(i)
}
}
console.log(numberBiggerThanFive);

Related

How to retrieve sub array elements when they fulfill the the condition and stop the loop

const winningTemplate = {
firstRow: [0, 1, 2, 3, 4],
secondRow: [5, 6, 7, 8, 9],
thirdRow: [10, 11, 13, 14],
fourthRow: [15, 16, 17, 18, 19],
lastRow: [20, 21, 22, 23, 24],
firstDiagonal: [0, 6, 18, 24],
firstColumn: [0, 5, 10, 15, 20],
secondColumn: [1, 6, 11, 16, 21],
thirdColumn: [2, 7, 17, 22],
fourthColumn: [3, 8, 13, 18, 23],
lastColumn: [4, 9, 14, 19, 24],
lastDiagonal: [4, 8, 16, 20],
}
export default winningTemplate;
let checkTemplate = Object.values(winningTemplate)
let isWinner = 0
for (let checkWinner of checkTemplate) {
for (let checkMatchedBird of checkWinner) {
const newWinnerMatchedArray =
updatedBirdClonePlayerOne[checkMatchedBird]
console.log('newWinnerMatchedArray', newWinnerMatchedArray)
if (newWinnerMatchedArray.includes('match')) {
break
}
// setWinner('wins')
}
// break;
}
I am expecting that any of the row column and diagonal elements are matched with using includes('match') then declare the winner.
every time the code executes the condition ('match') fulfills,and I see the array newWinnerMatchedArray has matched elements -which is going fine till now.
Now I want that anytime when 5 elements of any row or col or 4 elements of any diagonal array are matched we declare a winner and the loop stops. I hope it is cleared
You can label the loop and break that specific loop:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
loop1:
for (let i = 0; i < 5; i++) {
for(x of something) {
if (i === 1) {
break loop1;
}
}
str = str + i;
}
That being said I'd suggest simplifying your logic into pure functions and use the following:
forEach
map
reduce
some
every
These methods are more explicit about intention per line, and make it easier to read and manage. You can still obtain optimum performance in the algorhithm if you use them cleverly.

Split array into equal chunks, exclude the last chunk that is smaller and redistribute its items equally between the previous chunks

I have an array of items :
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
// or more items
I have managed to split it into chunks by 3 items per array and pushed them into an array of arrays :
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11] // <== the last one has less items than the others
]
I want to redistribute the items of the last array equally between the previous chunks :
// expected output
[
[1, 2, 3, 10],
[4, 5, 6, 11],
[7, 8, 9],
]
or even more complex like redistrbuting the items at random positions :
// expected output
[
[1, 2, 3, 10],
[4, 5, 6],
[7, 8, 9, 11],
]
so far this is what i have reached :
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
let arrayOfChunks = [];
let amount = 3;
for (let i = 0; i < array.length; i += amount) {
const chunk = array.slice(i, i + amount);
if (chunk.length === amount) {
arrayOfChunks.push(chunk);
} else {
console.log(chunk);
// output [10,11]
}
}
return arrayOfChunks;
I tried making another loop dpending on the arrayOfChunks.length = 3 where I could redistribute the items of the last array evenly into the arrayOfChunks, but sometimes the arrayOfChunks.length = 5 which require another splitting and merging into the previous generated equal chunks.
thanks for your help :)
After chunking the array normally, pop off the last subarray if the chunk number didn't divide the original array length evenly. Then, until that last popped subarray is empty, push items to the other subarrays, rotating indicies as you go.
const evenChunk = (arr, chunkSize) => {
const chunked = [];
for (let i = 0; i < arr.length; i += chunkSize) {
chunked.push(arr.slice(i, i + chunkSize));
}
if (arr.length % chunkSize !== 0) {
const last = chunked.pop();
let i = 0;
while (last.length) {
chunked[i].push(last.shift());
i = (i + 1) % chunked.length;
}
}
console.log(chunked);
};
evenChunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 7);
evenChunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3);

javascript applying function to different arrays

What i want to achieve:
A function that calculates the average score of an array with scores.
Make the function re-usable for different arrays
Achieved so-far:
const grades = [9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6];
function classAverage () {
let sumOfGrades = 0;
for(let i = 0; i < (grades.length); i++) {
sumOfGrades += grades[i];
}
const averageGrade = sumOfGrades/(grades.length);
return averageGrade;
}
classAverage(grades);
console.log(averageGrade);
This seem to work in my ide, here it produces an error averageGrade not defined.
Next i'd like this function to be apply-able to more arrays like grades1999 or grades2021 but the for loop inside the function uses the grades array for calculation, how can i achieve that this function would work with something like: classAverage grades(2019) arrays with different names.
Thank you for your time!
You need a parameter for the array inside of the function to calculate different arrays.
As result, you need an assignment of the returned value or use it directly without storing the result.
Then you could take the values directly with a for ... of statement.
Some hints:
By taking a property, you need not to wrap it in parentheses.
For getting the difference of local or global scope, have a look here: https://developer.mozilla.org/en-US/docs/Glossary/Scope
function classAverage (grades) {
let sumOfGrades = 0;
for(const grade of grades) {
sumOfGrades += grade;
}
return sumOfGrades/grades.length;
}
console.log(classAverage([9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6]));
See other comments for why your code failed.
Reduce is made for this
const numArrayAverage = arr => arr.reduce((a,b)=>a+b)/arr.length;
console.log(numArrayAverage([9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6]));
With input testing
const numArrayAverage = arr => Array.isArray(arr) && arr.length > 0 ? arr.reduce((a,b)=>a+b)/arr.length : "Invalid input";
console.log(numArrayAverage ([9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6]));
console.log(numArrayAverage ([]));
Just a few tweaks to what you have and it should run fine
const gradesData = [9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6];
function classAverage(grades) {
let sumOfGrades = 0;
for (let i = 0; i < (grades.length); i++) {
sumOfGrades += grades[i];
}
const averageGrade = sumOfGrades / (grades.length);
return averageGrade;
}
console.log(classAverage(gradesData));
You can add a method (classAverage) to the Array.prototype and then call it with different grade arrays.
Array.prototype.classAverage = function () {
return this.reduce((r, g) => r + g, 0) / (this.length || 1);
};
const grades = [9, 8, 5, 7, 7, 4, 9, 8, 8, 3, 6, 8, 5, 6];
const grades1999 = [1, 8, 3, 5, 7, 2, 4, 3];
const grades2020 = [5, 6, 7, 8, 2, 3, 4, 5, 6, 7, 8];
const grades2023 = [];
console.log(grades.classAverage());
console.log(grades1999.classAverage());
console.log(grades2020.classAverage());
console.log(grades2023.classAverage());

remove duplicate elements in proceeding arrays inside array of arrays

We have an array of arrays like this:
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
There may be duplicate elements in each array and that's fine.
But I'm after a proper solution to remove duplicate elements in each set comparing to lower sets!
So as we have a 0 in the first array and the last array, we should consider the 0 in last one a duplication and remove it...
the desired result would be:
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[12],
[14]
It's a confusing issue for me please help...
You could collect the values in an object with index as value, and filter for values who are at the same index.
const
arrays = [[0, 1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 9, 10, 11, 11], [2, 7, 10, 12], [0, 7, 10, 14]],
seen = {},
result = arrays.map((array, i) => array.filter(v => (seen[v] ??= i) === i));
result.forEach(a => console.log(...a));
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[4, 4, 5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
]
let filtered = arrays.map((row, i) => {
// concat all previous arrays
let prev = [].concat(...arrays.slice(0, i))
// filter out duplicates from prev arrays
return row.filter(r => !prev.includes(r))
})
console.log(filtered)
We can do this using Array#reduce and maintain a seen Set, which will have all visited numbers from each array.
Once you iterate over an array you push all visited elements in the seen Set, then push a new array filtered by the elements not in the seen Set:
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
const removeDupsInSibling = (arr) => {
let seen = new Set();
return arr.reduce((acc, a)=> {
const f = a.filter(v => !seen.has(v));
seen = new Set([...seen, ...a]);
acc.push(f);
return acc;
}, []);
}
console.log(removeDupsInSibling(arrays));
There are plenty of inefficient ways to do this, but if you want to do this in O(n), then we can make the observation that what we want to know is "which array a number is in". If we know that, we can run our algorithm in O(n):
for every element e in array at index i:
if index(e) == i:
this is fine
if index(e) < i:
remove this e
So let's just do literally that: we allocate an object to act as our lookup, and then we run through all elements:
const lookup = {};
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
const reduced = arrays.map((array, index) => {
// run through the elements in reverse, so that we can
// safely remove bad elements without affecting the loop:
for(let i=array.length-1; i>=0; i--) {
let value = array[i];
let knownIndex = (lookup[value] ??= index);
if (knownIndex < index) {
// removing from "somewhere" in the array
// uses the splice function:
array.splice(i,1);
}
}
return array;
});
console.log(reduced);
For an alternative, where the loop+splice is taken care of using filter, see Nina's answer.
Simple, clean and high performance solution:
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14]
];
const duplicates = {};
const answer = arrays.map( (array, level) => {
return array.filter( el => {
if ( duplicates[el] < level ) {
// return nothing; fine
} else {
duplicates[el] = level;
return el
}
})
});
console.log(JSON.stringify(answer))
here is on-liner and less-readable form:
const d = {}, arrays = [ [0, 1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 9, 10, 11, 11], [2, 7, 10, 12], [0, 7, 10, 14]];
const answer = arrays.map((a,l)=> a.filter(el=> d[el]<l ? 0 : (d[el]=l,el)));
console.log(JSON.stringify(answer))
const arrays = [
[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[2, 7, 10, 12],
[0, 7, 10, 14],
];
const output = arrays.reduce(
({ output, set }, current, i) => {
output[i] = current.filter((num) => !set.has(num));
[...new Set(output[i])].forEach((num) => set.add(num));
return { output, set };
},
{ output: [], set: new Set() }
).output;
console.log(output);
Gets the exact output you want:
[
[
0, 1, 2, 3,
4, 4, 4, 4
],
[
5, 6, 7, 8,
9, 10, 11, 11
],
[ 12 ],
[ 14 ]
]

Splice function to get rid of 6/7th of the entries in an array

I'm trying to understand where i'm going wrong here. say I have an array:
result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
I want to get rid of every 6 entries in my array, leave the 7th there, and go one. In effect i'm hoping to get rid of 6/7th of the values in my array. I'm thinking splice() could be perfect for that, but somehow the code below doesn't seem to work. Any suggestions?
Many thanks to you all!
function random_select ()
{
for(var i=0; i < result.length; i+7)
{
result.splice[i,6];
}
};
Try this instead:
var result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
for (var i = 0; i < result.length; i++) result.splice(i, 6);
This will:
First remove [0, 1, 2, 3, 4, 5], and let [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] be.
Next remove [7, 8, 9, 10, 11, 12] and let [13, 14, 15, 16] be.
Finally remove [13, 14, 15, 16].
Hence the result is [6, 13]. Is this what you want?

Categories

Resources