How to find a specific array in an array? - javascript

I have got this code:
var test = [[1,1], "b","a"];
function findArray(element) {
return element == [1,1];
}
console.log(test.find(findArray));
It returns:
undefined
What should I do to find the [1,1] array inside of the test array? (I do not want to loop through it though)

You can't compare two objects with === or == since they are references and will evaluate to true only if they are pointing to the same address.
You need to match each element from first array with respective index in second array to check for similarity, you can use every.
var test = [ [1, 1], "b", "a"];
function findArray(element) {
if(Array.isArray(element)){
let arrayToMatchWith = [1,1]
if(element.length === arrayToMatchWith.length){
return element.every((v,i)=> v === arrayToMatchWith[i])
}
}
return false
}
console.log(test.find(findArray));
console.log([[1,2]].find(findArray));
console.log([[1,1,1]].find(findArray));
console.log([[1]].find(findArray));
Could I pass the searched array as an argument?
Yes you can. Here I am using a curried function:
var test = [[1, 1], "b", "a"];
let curried = (arr) => (element) => {
if (Array.isArray(element)) {
if (element.length === arr.length) {
return element.every((v, i) => v === arr[i])
}
}
return false
}
let curried1 = curried([1,1])
console.log(test.find(curried1));
let curried2 = curried([1,2,2])
console.log([[1, 2]].find(curried2));
let curried3 = curried([1,1,1])
console.log([[1, 1, 1]].find(curried3));
let curried4 = curried([1])
console.log([[1]].find(curried4));

The array literal in your comparison is a different object than the array inside your original array. If you derive a comparable entity from each array, you can check for that inside the find method. One way to do it is by calling the toString method.
This is only required if you really don't want to loop through the array for comparison.
var test = [[1,1], "b","a"];
function findArray(element) {
if (element.constructor === Array)
return element.toString() == [1,1].toString();
}
console.log(test.find(findArray));

Related

Check if an element is an array using recursion

I would like to check if an element inside an array is another array. I'm solving a code challenge where the problem is iterating through an array and checking for a 7 but if an
element is an array I would like to continuously check each nested array for a 7.
I have console.log() in my first 'if' statement and I've seen that sevenBoom() is being called more than once. But for some reason it's not returning 'Boom!'
SevenBoom should return 'Boom!' if there's a seven.
function sevenBoom(arr) {
if (arr.includes(7)) {
return "Boom!";
}
arr.forEach((val) => {
if (Array.isArray(val)) sevenBoom(val);
});
}
sevenBoom([1, 3, 4, 6, [7]) // Returns undefined
sevenBoom([3, 7, 8, 9]) // Returns 'Boom!'
You could take a boolean value as result and use Array#some for checking arrays.
function hasSeven(array) {
function seven(a) {
return a.includes(7) || a.some(v => Array.isArray(v) && seven(v));
}
return seven(array)
? 'Boom!'
: 'There is no 7';
}
console.log(hasSeven([7]));
console.log(hasSeven([[7]]));
console.log(hasSeven([[[7]]]));
console.log(hasSeven([]));
console.log(hasSeven([[]]));
console.log(hasSeven([[[]]]));
const sevenBoom = (arr) => {
const recurse = (arr) => arr.some(n => Array.isArray(n) ? recurse(n) : n === 7);
if (recurse(arr)) {
return 'Boom';
}
}
This is assuming what should be returned other than 'Boom' is void. It's a bit of an awkward place for recursion since you want to return a string if you meet some criteria and nothing otherwise.
Firstly you need to return the value from your second if condition too.
But forEach() cannot be interrupted (for ex: with a return statement) and will run for all items. So you can keep track using a flag variable outside the forEach() and return your result on that basis.
function sevenBoom(arr) {
if (arr.includes(7)) {
return "Boom!";
}
let found = false;
arr.forEach((val) => {
if (Array.isArray(val)) if(sevenBoom(val)) found="Boom!";
})
return found;
}
console.log(sevenBoom([1,2,3]));
console.log(sevenBoom([1,2,7]));
console.log(sevenBoom([1,2,[2,7]]));
console.log(sevenBoom([1,2,[2,3,[4,5]]]));
console.log(sevenBoom([1,2,[2,3,[4,7]]]));
Note: How sevenBoom() can be directly used inside an if statement. This is because of the concept of truthy and falsy values.
PS: As mentioned above, forEach() will run for all items, no matter what. You can use any other looping mechanism like a simple for loop, some() etc. I just copied your code and hence used forEach()
I would check if an element is seven in the same loop that you are checking if an element is an array that way you can avoid going through the array unnecessarily.
const sevenBoom = arr => {
for (const ele of arr) {
if (ele === 7) return 'Boom';
if (Array.isArray(ele)) {
//this prevents you from halting your function early
//you only want to return in the loop if a 7 is found
if (boom(ele) === 'Boom') return 'boom'
}
}
}
You can use the .flat(depth) method to flatten each array before using the .includes() method. Choose a depth that would cover all possible arrays for your project.
function sevenBoom(arr) {
return arr.flat(10).includes(7) ? 'Boom!' : '-'
}
DEMO
let a = [1, 3, 4, 6, [7]],
b = [3, 7, 8, 9],
c = [1,2,[5,6,[3,5,[7,6]]]],
d = [0],
e = [1, [5, 4], 3, 5, [7]];
function sevenBoom(arr) {
return arr.flat(10).includes(7) ? 'Boom!' : '-'
}
for(let arr of [a,b,c,d,e]) {
console.log( sevenBoom( arr ) );
}
console.log( e ); //Original array remains unchanged
If 7 is not present in the root array, then your function isn't returning anything.
Try this, just a minor refactoring:
function sevenBoom(arr) {
if (arr.includes(7)) return 'Boom!';
for (let val of arr) {
if (Array.isArray(val)) {
if (sevenBoom(val)) return sevenBoom(val);
}
}
return false;
}

Javascript how do i get my function array to give me more then the first value

function countUniqueItems(arr) {
nums = [];
for (i = 0; i < arguments.length; i++) {
const item = arr[i];
console.log(i);
//console.log(item);
if (nums.includes(arr) === true) {
//console.log('8 is in the array');
//nums.push(arr)
} else {
nums.push(arr);
//console.log('8 is NOT in the array');
//nums.push(item)
}
}
return nums;
}
countUniqueItems(1, 2);
So it will give back the first argument which is 1 but i want it to be able to say argument 2 and 3 and so on
So you need to pass an array into the function, in place of 1,2 pass [1,2].
Then inside your function, you should use arr.length in place of arguments.length.
Then you look at your logic for the loop, you are pushing atm arr into nums, but if you pass and array that isn't really want you want, you should be pushing item as that is the variable which represents your current element from the array.
It looks from you comments like you're trying to make a unique list of inputs. Perhaps something like this would do the trick.
EDIT: Updated to use arguments
function uniqueNumbers() {
let arrayOfArguments = [...arguments]
let uniqueNums = [];
arrayOfArguments.map(i => !uniqueNums.includes(i) ? uniqueNums.push(i) : null);
return uniqueNums;
};
console.log(uniqueNumbers(1,2,3,3));
you should either pass an array to countUniqueItems or use the arguments keyword in the for-loop.
Your code is only seeing 1 (as arr inside the function).
basic implementation to find unique items
function countUniqueItems(...arr) {
let nums = [];
for (let num of arr) {
if (nums.indexOf(num) === -1) nums.push(num);
}
return nums;
}
console.log(countUniqueItems(1, 2, 1));
Using Set you can remove the duplicate values, you dont need to do logic run the loop to find the unique values from array.
const a = [1,2,3,3];
const uniqueSet = new Set(a);
uniqueSet.size
let uniqueFinder = arr => { const uniqueSet = new Set(arr); return uniqueSet.size}
const arrywithduplicates = [1,2,3,3,4,4];
uniqueFinder(arrywithduplicates) // return 4
Read more about Set : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

How to know if array / object is empty after delete function?

var arr = [30];
delete arr[0];
if (arr.length == 0) {
alert("empty");
}
This code won't work only because of delete.
Is there an ultimate way to check if the array is empty no matter what?
Thanks :)
You can use Object.values() to get actual values from the array. If the length of the values array is 0, then the array is empty by your definition.
const checkIfSparseIsEmpty = arr => !Object.values(arr).length
var arr1 = [30];
delete arr1[0];
console.log(checkIfSparseIsEmpty(arr1)) // true
var arr2 = [1, 2, 3]
delete arr2[0]
delete arr2[1]
console.log(checkIfSparseIsEmpty(arr2)) // false
console.log(checkIfSparseIsEmpty(Array(10))) // true
The reason behind the expected behaviour is that when you use the delete operator, it replaces the element by undefined, and since the length doesn't change the above check does not work.
One of the ways to effectively delete an element from the array is to use the filer array function.
Example:
function deleter(arr, toDelete) {
let newArray = arr.filter((ar) => {
return ar !== toDelete;
})
return newArray;
}
let array = [1,2,3,4,5]
console.log(deleter(array, 5));
Now to check if an element exists in an array, you can use the indexOf method available on the array prototype.
Following is an example:
function deleter(arr, toDelete) {
let newArray = arr.filter((ar) => {
return ar !== toDelete;
})
return newArray;
}
let array = [1,2,3,4,5]
let toDelete = 5;
let newArr = deleter(array, toDelete);
console.log(newArr.indexOf(toDelete))
// -1 corresponds to the element not found.

Negate values from array with OR operator

This is a very simple question but I am not been able to wrap my head around it.
I have an array of pages with n number of page names, I want to run a loop with some page names not included in it.
var arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
for (var page in arr) {
if (arr[page] !== "page-name" || arr[page] !== "some-more") {
console.log(arr[page])
}
}
Now the result that I want is this:
page-name-two
page-3
another-page
What am I doing wrong?
Just take logical AND && instead of logical OR ||.
Please use a for loop with a variable for the index instead of the keys of an object.
Source:
Why is using “for…in” with array iteration a bad idea?
var arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
for (var i = 0; i < arr.length; i++) {
if (arr[i] !== "page-name" && arr[i] !== "some-more") {
console.log(arr[i]);
}
}
The expression
arr[i] !== "page-name" || arr[i] !== "some-more"
is always true, because for exampe if
arr[i] === "page-name"
then the other part is true, because of
"page-name" !== "some-more"`.
You should use .filter() to filter values from first array and then perform whatever action you want to perform on resultant array. This will save your from writing a lot of OR / AND conditions in case you need to filter more values.
let arr1 = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'],
arr2 = ["page-name", 'some-more'];
let result = arr1.filter(s => !arr2.includes(s));
console.log(result);
I would store the values that you're looking to eliminate, then run Array.filter on your list of all page names to find matches. If a name matches, remove it from the final array.
// This can be a array of whatever strings you're looking to eliminate from the array
const valuesToFilter = ['page-name', 'some-more'];
// Your original array
const arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
// Use Array.filter to eliminate anything that doesn't pass the filter test
const filteredArr = arr.filter(page => {
let foundMatch = false;
valuesToFilter.forEach(value => {
if (page === value) {
foundMatch = true;
}
})
if (!foundMatch) return page;
});
console.log(filteredArr);

Check if array has element(s) from another array

I have two arrays A = [0,1,2] and B = [2,1,0]. How to check if a number in A is present in B?
NOTE: includes is not ES6, but ES2016 Mozilla docs. This will break if you transpile ES6 only.
You can use Array#every method(to iterate and check all element passes the callback function) with Array#includes method(to check number present in B).
A.every( e => B.includes(e) )
const A = [0, 1, 2],
B = [2, 1, 0],
C=[2, 1];
console.log(A.every(e => B.includes(e)));
console.log(A.every(e => C.includes(e)));
console.log(C.every(e => B.includes(e)));
To check a single element present in the second array do:
A[0].includes(e)
//^---index
Or using Array#indexOf method, for older browser.
A[0].indexOf(e) > -1
Or in case you want to check at least one element present in the second array then you need to use Array#some method(to iterate and check at least one element passes the callback function).
A.some(e => B.includes(e) )
const A = [0, 1, 2],
B = [2, 1, 0],
C=[2, 1],D=[4];
console.log(A.some(e => B.includes(e)));
console.log(A.some(e => C.includes(e)));
console.log(C.some(e => B.includes(e)));
console.log(C.some(e => D.includes(e)));
Here's a self defined function I use to compare two arrays. Returns true if array elements are similar and false if different. Note: Does not return true if arrays are equal (array.len && array.val) if duplicate elements exist.
var first = [1,2,3];
var second = [1,2,3];
var third = [3,2,1];
var fourth = [1,3];
var fifth = [0,1,2,3,4];
console.log(compareArrays(first, second));
console.log(compareArrays(first, third));
console.log(compareArrays(first, fourth));
console.log(compareArrays(first, fifth));
function compareArrays(first, second){
//write type error
return first.every((e)=> second.includes(e)) && second.every((e)=> first.includes(e));
}
If the intent is to actually compare the array, the following will also account for duplicates
const arrEq = (a, b) => {
if (a.length !== b.length) {
return false
}
const aSorted = a.sort()
const bSorted = b.sort()
return aSorted
.map((val, i) => bSorted[i] === val)
.every(isSame => isSame)
}
Hope this helps someone :D
If you just need to know whether A and B has same entries, simply
JSON.stringify(A.concat().sort()) === JSON.stringify(B.concat().sort())
Note:
If there are null and undefined in each array, it will be true. Because JSON#stringify converts undefined to null.
JSON.stringify([null].concat().sort()) === JSON.stringify([undefined].concat().sort())
// true
A.length === B.length && A.every(e => B.includes(e))

Categories