Javascript includes() failing [duplicate] - javascript

This question already has answers here:
Check if an array includes an array in javascript
(3 answers)
Why doesn't equality check work with arrays [duplicate]
(6 answers)
Closed 1 year ago.
Why are the last two console.logs showing false?
const a = 'one';
const b = 'two';
const myArray = [[ 'one', 'two'], ['three', 'four'], ['five', 'six']];
console.log([a, b]);
console.log(myArray[0]);
console.log(myArray.includes([a, b]));
console.log(myArray[0] === [a, b]);

in JavaScript arrays and objects are compared by reference and not by value.
One solution I suggest is to use JSON.stringify()
a = ["a", "b"]
b = ["a", "b"]
console.log(JSON.stringify(a) == JSON.stringify(a)) // return true

Array.prototype.includes() and triple equal operator === work with references, they don't compare the elements of the arrays, they compare the array references themselves:
console.log([] === []); // false
const a = [];
const b = a;
console.log(a === b); // true

You could first convert the array (object) to a string using JSON.stringify(), then compare the string:
const a = 'one';
const b = 'two';
const myArray = [
['one', 'two'],
['three', 'four'],
['five', 'six']
];
console.log(JSON.stringify(myArray[0]) === JSON.stringify([a, b]));
You can also run through the separate values using every() and compare them like this:
const a = 'one';
const b = 'two';
const myArray = [[ 'one', 'two'], ['three', 'four'], ['five', 'six']];
const isequal = [a, b].length === myArray[0].length && [a, b].every((value, i) => value === myArray[0][i]);
console.log(isequal);

Arrays in JavaScript are Objects and Objects comparison will always return false if the referenced objects aren't the same.
If you want to compare arrays you have to write a function for this or use isEqual func from lodash
https://lodash.com/docs/4.17.15#isEqual

Related

return reordered version of array b based on reordered version of a [duplicate]

This question already has answers here:
Javascript - sort array based on another array
(26 answers)
Closed last year.
I have two arrays a and b like this:
const a = [1,2,3,4]
const b = ['1','2','3','4'] // could be 'a','b','c','d'
const reordered_a = [4,1,3,2] // based on this reordering
function reorder_b() {
// should return ['4','1','3','2']
}
How can I return reordered version of b based on reordered positions in reordered_a?
You could take an object with the indices for the values and map the pattern with the values of the indices.
const a = [1, 2, 3, 4]
const b = ['1', '2', '3', '4'] // could be 'a','b','c','d'
const reordered_a = [4, 1, 3, 2] // based on this reordering
function reorder_b() {
const references = Object.fromEntries(Object.entries(a).map(a => a.reverse()));
return reordered_a.map(k => b[references[k]]);
}
console.log(reorder_b()); // 4 1 3 2
What you got to do is first use every pair of elements el1 and el2 and convert them to numbers. Then once they're converted, make sure that the latter is bigger than the latter by checking their difference :
return b.sort((el1,el2)=>Number(el2)-Number(el1))

Javascript map method: Wrapping the argument in curly braces results in an array of objects [duplicate]

This question already has answers here:
Javascript object literal: what exactly is {a, b, c}?
(3 answers)
Closed 1 year ago.
I am trying to figure out why the following code results in an array of objects:
const startingArray = ['One', 'Two', 'Three', 'Four', 'Five'];
let endingArray = startingArray.map((nums) => {
return { nums }
});
console.log(endingArray)
The result would be an array of objects such as:
[{nums: 'One'}
{nums: 'Two'}...]
and continuing on through the end of the input array...
I understand that the map() method creates a new array populated with the results of calling a provided function on every element in the calling array. So is it simply a matter of the fact that by wrapping the argument in curly braces the map method inherently sets the argument name as the key of an object literal and sets the value of the input array as the associated value of the respective key?
{num} here is shorthand to {'num' : num}
Checkout x in the below code:
let a = 22;
let x = { a};
console.log(x);
const startingArray = ['One', 'Two', 'Three', 'Four', 'Five'];
let endingArray = startingArray.map((nums) => {
return {nums}
});

Javascript, If statement with dictionary value equal to array? [duplicate]

This question already has answers here:
How to compare arrays in JavaScript?
(55 answers)
Closed 3 years ago.
I am fairly new to javascript and for some reason my program doesn't work. I have a dictionary using the key set to a string and the value euqal to an array full of booleans, I.E:
dict = {x: [true, false]}
but for some reason when I run the dictionary through an if statement, like
if (dict[x] == [true, false]) {do something }
it fails to trigger. I was wondering what I am doing wrong
Comapre using Array.every
You can use Array.every to check if all items in an array verify a certain condition
With that you can check if all items in arrayOne are equal to the item at index i from arrayTwo
Here's an example
const isEqualArrays = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]);
const isEqualDicts = (a, b) => isEqualArrays(a.x, b.x);
const first = { x: [true, false, true] };
const second = { x: [true, false, true] };
const unequal = { x: [true, true, true] };
console.log(isEqualDicts(first, second));
console.log(isEqualDicts(first, unequal));
Use JSON.stringify
Another way that works with your example, is to convert the objects ("dicts") into strings and then compare those strings. It looks like this
const compareDicts = (a, b) => JSON.stringify(a) === JSON.stringify(b);
const first = { x: [true, false, true] };
const second = { x: [true, false, true] };
const unequal = { x: [true, true, true] };
console.log(compareDicts(first, second));
console.log(compareDicts(first, unequal));
Arrays and Objects are not primitive types but reference types in JavaScript.
This means that when comparing arrays and objects, you are actually comparing the references to these entities, and not their content. When you assign this array to another variable, you are simply making that variable reference the same content, but you are not copying this content:
const a = [1, 2, 3];
const b = [1, 2, 3];
console.log(a !== b);
const c = a;
console.log(a === c);
c[0] = 10;
console.log(a);
In your case, if you want to make sure your array contains true followed by false, you can use Array.every() or more simply just use array indexing to check the elements since the array is short:
const a = [true, false];
if (a.every((x, i) => x === [true, false][i])) {
console.log('same content');
}
if (a[0] === true && a[1] === false) {
console.log('same content');
}
You can not compare complex structures like arrays and objects because the equality checking is actually looking at specific memory locations. Every time you create a new object or array, that variable is pointing to a new, unique place in memory. You would have to iterate through the keys/indices that hold primitive values and check each one for equality with your other structure.
Extra credit: the square and curly braces are called Array literals and Object literals. They are essentially syntactic sugar for new Array or new Object.
Additionally, the reason you can check equality on strings, booleans, and numbers is because each value of each type (true, false, 7, 'hello world', 'blue', 42), actually points to a unique place in memory. For example: when you write
var str = 'yellow'
the variable str is now pointing to a place in memory that is associated with the six characters that comprise the word ‘yellow’. This is the actual reason that equality checking is possible.
var str2 = 'yel' + 'low'
Results in the same combination of characters, which results in a reference to the same memory address as what str’s valueOf function points to. Therefore:
str === str2 // true
I hope that helps. There’s much more down this rabbit hole, but this should get you started.

find an array in another array in javascript [duplicate]

This question already has answers here:
How to compare arrays in JavaScript?
(55 answers)
Closed 4 years ago.
Is there any function in JS to check "If an array exists in a larger array?"
I tried array.includes() and array.indexOf() but they didn't work for me...
for example I except a true return value here:
parent = [[a,b],[c,d],[e,f]]
child = [c,d]
Your includes fails because you're trying to match reference. A well detailed explanation you can see on this answer https://stackoverflow.com/a/54363784/9624435
You can use filter and every
let parent = [['a','b'],['c','d'],['e','f']];
let child = ['c','d'];
let result = parent.filter(arr => arr.every(v => child.includes(v)));
console.log(result);
Let's focus on why .includes fail.
Array.includes uses following function to check equality:
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
Since you have arrays as element, they are copied using references, so you are checking references of arrays instead. Hence it fails.
Following is a sample:
const item1 = ['a', 'b'];
const item2 = ['c', 'd'];
const item3 = ['e', 'f']
const parent = [item1, item2, item3]
const child = item3;
console.log(parent.includes(child))
Hence, you will have to go deeper and check individual values.
References:
Why [] == [] is false in JavaScript?
Array.includes polyfill
How to compare arrays in JavaScript?: as rightly suggested by #Chris G

Merge multiple arrays together if not null

I am building a React App and am using Async Actions to make request to outside API's and bring in data into my app. I have 4 arrays that I need to merge together. Since I am using Async Actions the default values if theres no data is null. I want to check to see if the array is not null and if it has a value then merge it with the others into a single array. Once I have all the data into a single array I am going to use the includes method to see if any of the values are present in the array. Using the spread operator I don't think is going to work here as it will fail as null is not an iterable. Is there a way to do this with reduce to check through each of the 4 separate arrays make sure the value is not null and then combine them together into one array.
Your question leads you to the answer. :)
Essentially you are asking how to filter all non-array inputs and then combine (or concatenate) them together into a new array.
A couple of notes on the following approach:
For better stability in filtering, rather than using a blacklist (not null), use a whitelist (Array.isArray) to ensure only arrays are combined.
The spread operator can be used to then create an arguments list for a new array's concat method.
const arr1 = [1,2];
const arr2 = null;
const arr3 = [3,4];
const arr4 = [5];
const concat = (...arrays) => [].concat(...arrays.filter(Array.isArray));
console.log(concat(arr1, arr2, arr3, arr4));
For a bit of fun, if the combined array needs to be unique values (assuming simple types for values) then including a quick cast to a Set and back to an Array can make that happen:
const arr1 = [1,2];
const arr2 = null;
const arr3 = [3,4];
const arr4 = [4,5];
const concat = (...arrays) =>[].concat(...arrays.filter(Array.isArray));
const unique = (array) => [...new Set(array)];
const concated = concat(arr1, arr2, arr3, arr4);
const uniqued = unique(concated);
console.log({concated, uniqued});
Here is a one line solution (ES6).
At the first part, we merge all arrays, and then filter array elements - we include only "not null" values and exclude duplicates:
const arr1 = [1, null, 6, 'q'],
arr2 = null,
arr3 = [1, 1, null, 1],
arr4 = ['e', 'q', 6, 1, null];
const final = []
.concat(arr1, arr2, arr3, arr4)
.filter((item, i, arr) => item && arr.indexOf(item) === i);
console.log(final); // Expected output: [1, 6, "q", "e"]
var a = [1, 2, 3]
var b = null
var c = [...a||[], ...b||[]]
console.log(c)
If you assign your arrays to properties of an object obj, you can simply iterate over the object :
const a = ["a", "1"], b = null, c = ["c", 78], d = []
const obj = { a, b, c, d }
let res = []
for(let key in obj) {
res = res.concat(Array.isArray(obj[key]) ? obj[key] : []);
}
console.log(res)

Categories