JS Methods That Blew My Mind - Array.prototype.every() & Array.prototype.some()
Okay, I've used forEach(), map(), filter() and my good old reliable friend for loop on arrays, but what the heck is every() and why/when would I need it?
Array.prototype.every()
I came across this method when trying to solve a coding problem where I was asked to write a function(str1, str2) that returns true if a portion of str1 characters can be rearranged to match str2, otherwise returns false.
My first solution was as below:
function scramble(str1, str2) {
let targetObj = {}
for (let i = 0; i < str2.length; i++) {
let char = str2[i]
targetObj[char] ? targetObj[char] += 1 : targetObj[char] = 1
}
for (let i = 0; i < str1.length; i++) {
let char = str1[i]
if (targetObj[char]) {
targetObj[char] -= 1
if (targetObj[char] == 0) {
delete targetObj[char]
if (Object.keys(targetObj) == 0) return true
}
}
}
return false
}
It passed all tests once, but later when I tried submitting it again, the tests timed out -- it didn't handle long strings well.
Inspired by others' solutions, I tried using Array.prototype.every() in my second try:
function scramble(str1, str2) {
let str1Obj = {}
for (let i = 0; i < str1.length; i++) {
let char = str1[i]
str1Obj[char] ? str1Obj[char] += 1 : str1Obj[char] = 1
}
return **str2.split('').every(char => --str1Obj[char] >= 0)**
}
This solution passed all tests, and took 10627ms.
It's interesting to note that when written the return in the way shown below, it took longer(11024ms):
return str2.split('').every(char => {
str1Obj[char] -= 1
return str1Obj[char] >= 0
})
I also tried writing the first part of Solution 2 using Array.prototype.reduce(), and noticed that it was indeed slower than a for loop -- it took 11057ms to pass all tests, and when combined with the longer version of return above, it timed out.
let str1Obj = str1.split('').reduce((obj, char) => {
obj[char] ? obj[char] += 1 : obj[char] = 1
return obj
}, {})
Final working code with comments:
function scramble(str1, str2) {
// using reduce:
/*
let str1Obj = str1.split('').reduce((obj, char) => {
obj[char] ? obj[char] += 1 : obj[char] = 1
return obj
}, {})
*/
// using for loop
let str1Obj = {}
for (let i = 0; i < str1.length; i++) {
let char = str1[i]
str1Obj[char] ? str1Obj[char] += 1 : str1Obj[char] = 1
}
// 11024ms with for loop
/*
return str2.split('').every(char => {
str1Obj[char] -= 1
return str1Obj[char] >= 0
})
*/
// 10627ms with for loop, 11057ms with reduce
return str2.split('').every(char => --str1Obj[char] >= 0)
}
const array = [1, 2, 3, 4, 5]
// Tests if some elements in array are even numbers:
console.log(array.some(num => num % 2 === 0)) // true
Syntax:
some((element, index, array) => { /* … */ } ) // index and array are optional parameters