I need to find arrays where all values are equal. What's the fastest way to do this? Should I loop through it and just compare values?
['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
const allEqual = arr => arr.every( v => v === arr[0] )
allEqual( [1,1,1,1] ) // true
Or one-liner:
[1,1,1,1].every( (val, i, arr) => val === arr[0] ) // true
Array.prototype.every (from MDN) :
The every() method tests whether all elements in the array pass the test implemented by the provided function.
Edit: Be a Red ninja:
!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Results:
var array = ["a", "a", "a"] => result: "true"
var array = ["a", "b", "a"] => result: "false"
var array = ["false", ""] => result: "false"
var array = ["false", false] => result: "false"
var array = ["false", "false"] => result: "true"
var array = [NaN, NaN] => result: "false"
Warning:
var array = [] => result: TypeError thrown
This is because we do not pass an initialValue. So, you may wish to check array.length first.
You can turn the Array into a Set. If the size of the Set is equal to 1, then all elements of the Array are equal.
function allEqual(arr) {
return new Set(arr).size == 1;
}
allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
This works. You create a method on Array by using prototype.
if (Array.prototype.allValuesSame === undefined) {
Array.prototype.allValuesSame = function() {
for (let i = 1; i < this.length; i++) {
if (this[i] !== this[0]) {
return false;
}
}
return true;
}
}
Call this in this way:
let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame(); // false
In JavaScript 1.6, you can use Array.every:
function AllTheSame(array) {
var first = array[0];
return array.every(function(element) {
return element === first;
});
}
You probably need some sanity checks, e.g. when the array has no elements. (Also, this won't work when all elements are NaN since NaN !== NaN, but that shouldn't be an issue... right?)
And for performance comparison I also did a benchmark:
function allAreEqual(array){
if(!array.length) return true;
// I also made sure it works with [false, false] array
return array.reduce(function(a, b){return (a === b)?a:(!b);}) === array[0];
}
function same(a) {
if (!a.length) return true;
return !a.filter(function (e) {
return e !== a[0];
}).length;
}
function allTheSame(array) {
var first = array[0];
return array.every(function(element) {
return element === first;
});
}
function useSome(array){
return !array.some(function(value, index, array){
return value !== array[0];
});
}
Results:
allAreEqual x 47,565 ops/sec ±0.16% (100 runs sampled)
same x 42,529 ops/sec ±1.74% (92 runs sampled)
allTheSame x 66,437 ops/sec ±0.45% (102 runs sampled)
useSome x 70,102 ops/sec ±0.27% (100 runs sampled)
So apparently using builtin array.some() is the fastest method of the ones sampled.
update 2022 version: use Set()
let a = ['a', 'a', 'b', 'a'];
let b = ['a', 'a', 'a', 'a'];
const check = (list) => {
const setItem = new Set(list);
return setItem.size <= 1;
}
const checkShort = (list) => (new Set(list)).size <= 1
check(a); // false;
check(b); // true;
checkShort(a); // false
checkShort(b); // true
Update new solution: check index
let a = ['a', 'a', 'b', 'a'];
let b = ['a', 'a', 'a', 'a'];
let check = (list) => list.every(item => list.indexOf(item) === 0);
check(a); // false;
check(b); // true;
Updated with ES6:
Use list.every is the fastest way:
let a = ['a', 'a', 'b', 'a'];
let check = (list) => list.every(item => item === list[0]);
old version:
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];
function areWeTheSame(list) {
var sample = list[0];
return (list.every((item) => item === sample));
}
If you're already using underscore.js, then here's another option using _.uniq:
function allEqual(arr) {
return _.uniq(arr).length === 1;
}
_.uniq returns a duplicate-free version of the array. If all the values are the same, then the length will be 1.
As mentioned in the comments, given that you may expect an empty array to return true, then you should also check for that case:
function allEqual(arr) {
return arr.length === 0 || _.uniq(arr).length === 1;
}
Shortest answer using underscore/lodash
function elementsEqual(arr) {
return !_.without(arr, arr[0]).length
}
spec:
elementsEqual(null) // throws error
elementsEqual([]) // true
elementsEqual({}) // true
elementsEqual([1]) // true
elementsEqual([1,2]) // false
elementsEqual(NaN) // true
edit:
Or even shorter, inspired by Tom's answer:
function elementsEqual2(arr) {
return _.uniq(arr).length <= 1;
}
spec:
elementsEqual2(null) // true (beware, it's different than above)
elementsEqual2([]) // true
elementsEqual2({}) // true
elementsEqual2([1]) // true
elementsEqual2([1,2]) // false
elementsEqual2(NaN) // true
every() function check if all elements of an array
const checkArr = a => a.every( val => val === a[0] )
checkArr(['a','a','a']) // true
You can use Array.every if supported:
var equals = array.every(function(value, index, array){
return value === array[0];
});
Alternatives approach of a loop could be something like sort
var temp = array.slice(0).sort();
var equals = temp[0] === temp[temp.length - 1];
Or, if the items are like the question, something dirty like:
var equals = array.join('').split(array[0]).join('').length === 0;
Also works.
Yes, you can check it also using filter as below, very simple, checking every values are the same as the first one:
//ES6
function sameValues(arr) {
return arr.filter((v,i,a)=>v===a[0]).length === arr.length;
}
also can be done using every method on the array:
//ES6
function sameValues(arr) {
return arr.every((v,i,a)=>v===a[0]);
}
and you can check your arrays like below:
sameValues(['a', 'a', 'a', 'a']); // true
sameValues(['a', 'a', 'b', 'a']); // false
Or you can add it to native Array functionalities in JavaScript if you reuse it a lot:
//ES6
Array.prototype.sameValues = Array.prototype.sameValues || function(){
this.every((v,i,a)=>v===a[0]);
}
and you can check your arrays like below:
['a', 'a', 'a', 'a'].sameValues(); // true
['a', 'a', 'b', 'a'].sameValues(); // false
You can get this one-liner to do what you want using Array.prototype.every, Object.is, and ES6 arrow functions:
const all = arr => arr.every(x => Object.is(arr[0], x));
Now you can make use of sets to do that easily.
let a= ['a', 'a', 'a', 'a']; // true
let b =['a', 'a', 'b', 'a'];// false
console.log(new Set(a).size === 1);
console.log(new Set(b).size === 1);
I think the simplest way to do this is to create a loop to compare the each value to the next. As long as there is a break in the "chain" then it would return false. If the first is equal to the second, the second equal to the third and so on, then we can conclude that all elements of the array are equal to each other.
given an array data[], then you can use:
for(x=0;x<data.length - 1;x++){
if (data[x] != data[x+1]){
isEqual = false;
}
}
alert("All elements are equal is " + isEqual);
You can convert array to a Set and check its size
In case of primitive array entries, i.e. number, string:
const isArrayWithEqualEntries = array => new Set(array).size === 1
In case of array of objects with some field to be tested for equivalence, say id:
const mapper = ({id}) => id
const isArrayWithEqualEntries = array => new Set(array.map(mapper)).size === 1
You can use this:
function same(a) {
if (!a.length) return true;
return !a.filter(function (e) {
return e !== a[0];
}).length;
}
The function first checks whether the array is empty. If it is it's values are equals..
Otherwise it filter the array and takes all elements which are different from the first one. If there are no such values => the array contains only equal elements otherwise it doesn't.
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];
Its Simple.
Create a function and pass a parameter.
In that function copy the first index into a new variable.
Then Create a for loop and loop through the array.
Inside a loop create an while loop with a condition checking whether the new created variable is equal to all the elements in the loop.
if its equal return true after the for loop completes else return false inside the while loop.
function isUniform(arra){
var k=arra[0];
for (var i = 0; i < arra.length; i++) {
while(k!==arra[i]){
return false;
}
}
return true;
}
The accepted answer worked great but I wanted to add a tiny bit. It didn't work for me to use === because I was comparing arrays of arrays of objects, however throughout my app I've been using the fast-deep-equal package which I highly recommend. With that, my code looks like this:
let areAllEqual = arrs.every((val, i, arr) => equal(val, arr[0]) );
and my data looks like this:
[
[
{
"ID": 28,
"AuthorID": 121,
"VisitTypeID": 2
},
{
"ID": 115,
"AuthorID": 121,
"VisitTypeID": 1
},
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
],
[
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
],
[
{
"ID": 5,
"AuthorID": 121,
"VisitTypeID": 1
},
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
]
]
You could use a for loop:
function isEqual(arr) {
var first = arr[0];
for (let i = 1; i < arr.length; i++) {
if (first !== arr[i]) {
return false;
}
}
return true;
}
Underscore's _.isEqual(object, other) function seems to work well for arrays. The order of items in the array matter when it checks for equality. See http://underscorejs.org/#isEqual.
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];
function areWeTheSame(list) {
var sample = list[0];
return !(list.some(function(item) {
return !(item == sample);
}));
}
function isUniform(array) {
for (var i=1; i< array.length; i++) {
if (array[i] !== array[0]) { return false; }
}
for (var i=1; i< array.length; i++) {
if (array[i] === array[0]) { return true; }
}
}
For the first loop; whenever it detects uneven, returns "false"
The first loop runs, and if it returns false, we have "false"
When it's not return false, it means there will be true, so we do the second loop. And of course we will have "true" from the second loop (because the first loop found it's NOT false)
Create a string by joining the array.
Create string by repetition of the first character of the given array
match both strings
function checkArray(array){
return array.join("") == array[0].repeat(array.length);
}
console.log('array: [a,a,a,a]: ' + checkArray(['a', 'a', 'a', 'a']));
console.log('array: [a,a,b,a]: ' + checkArray(['a', 'a', 'b', 'a']));
And you are DONE !
Another interesting way when you use ES6 arrow function syntax:
x = ['a', 'a', 'a', 'a']
!x.filter(e=>e!==x[0])[0] // true
x = ['a', 'a', 'b', 'a']
!x.filter(e=>e!==x[0])[0] // false
x = []
!x.filter(e=>e!==x[0])[0] // true
And when you don't want to reuse the variable for array (x):
!['a', 'a', 'a', 'a'].filter((e,i,a)=>e!==a[0])[0] // true
IMO previous poster who used array.every(...) has the cleanest solution.
this might work , you can use the comment out code as well that also woks well with the given scenerio.
function isUniform(){
var arrayToMatch = [1,1,1,1,1];
var temp = arrayToMatch[0];
console.log(temp);
/* return arrayToMatch.every(function(check){
return check == temp;
});*/
var bool;
arrayToMatch.forEach(function(check){
bool=(check == temp);
})
console.log(bool);
}
isUniform();
Use index of operator for every item of array
to check if it exists or not. If even one item returns -1 (doesn't exist then it will be false)
nst arr1 = [1, 3, 5];
const arr2 = [5, 7, 9];
const arr3 = [1, 3, 5];
arr1.every(item => arr2.indexOf(item) != -1)
// this will return false
arr1.every(item => arr3.indexOf(item) != -1)
// this will return true
Simple one line solution, just compare it to an array filled with the first entry.
if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
**// Logical Solution:- Declare global array and one variable(To check the condition) whether all element of an array contains same value or not.**
var arr =[];
var isMatching = false;
for(var i=0;i<arr.length;i++){
if(String(arr[i]).toLowerCase()== "Your string to check"){
isMatching=true;
// Array has same value in all index of an array
}
else{
isMatching=false;
// Array Doesn't has same value in all index of an array
break;
}
}
// **Check isMatching variable is true or false**
if(isMatching){ // True
//If Array has same value in all index, then this block will get executed
}
else{ //False
//If Array doesn't has same value in all index, then this block will get executed
}
Related
I want a function that returns true if and only if a given array includes all the elements of a given "target" array. As follows.
const target = [ 1, 2, 3, ];
const array1 = [ 1, 2, 3, ]; // true
const array2 = [ 1, 2, 3, 4, ]; // true
const array3 = [ 1, 2, ]; // false
How can I accomplish the above result?
You can combine the .every() and .includes() methods:
let array1 = [1,2,3],
array2 = [1,2,3,4],
array3 = [1,2];
let checker = (arr, target) => target.every(v => arr.includes(v));
console.log(checker(array2, array1)); // true
console.log(checker(array3, array1)); // false
The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value. Stands to reason that if you call every() on the original array and supply to it a function that checks if every element in the original array is contained in another array, you will get your answer. As such:
const ar1 = ['a', 'b'];
const ar2 = ['c', 'd', 'a', 'z', 'g', 'b'];
if(ar1.every(r => ar2.includes(r))){
console.log('Found all of', ar1, 'in', ar2);
}else{
console.log('Did not find all of', ar1, 'in', ar2);
}
You can try with Array.prototype.every():
The every() method tests whether all elements in the array pass the test implemented by the provided function.
and Array.prototype.includes():
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
var mainArr = [1,2,3];
function isTrue(arr, arr2){
return arr.every(i => arr2.includes(i));
}
console.log(isTrue(mainArr, [1,2,3]));
console.log(isTrue(mainArr, [1,2,3,4]));
console.log(isTrue(mainArr, [1,2]));
I used Purely Javascript.
function checkElementsinArray(fixedArray,inputArray)
{
var fixedArraylen = fixedArray.length;
var inputArraylen = inputArray.length;
if(fixedArraylen<=inputArraylen)
{
for(var i=0;i<fixedArraylen;i++)
{
if(!(inputArray.indexOf(fixedArray[i])>=0))
{
return false;
}
}
}
else
{
return false;
}
return true;
}
console.log(checkElementsinArray([1,2,3], [1,2,3]));
console.log(checkElementsinArray([1,2,3], [1,2,3,4]));
console.log(checkElementsinArray([1,2,3], [1,2]));
If you are using ES5, then you can simply do this.
targetArray =[1,2,3];
array1 = [1,2,3]; //return true
array2 = [1,2,3,4]; //return true
array3 = [1,2] //return false
console.log(targetArray.every(function(val) { return array1.indexOf(val) >= 0; })); //true
console.log(targetArray.every(function(val) { return array2.indexOf(val) >= 0; })); // true
console.log(targetArray.every(function(val) { return array3.indexOf(val) >= 0; }));// false
reduce can be used here as well (but it has O = (N * M) difficulty):
const result = target.reduce((acc, el) => {
return acc && array.includes(el)
}, true);
To solve this in more efficient way(O = N + M):
const myMap = new Map();
array.forEach(element => myMap.set(element);
const result = target.reduce((acc, el) => {
return acc && myMap.has(el)
}, true);
If you're checking if array x contains everything in array y, including requiring multiple occurrences of elements in y to appear multiple times in x:
function arrayContains(x,y) {
// returns true if array x contains all elements in array y
return !x.reduce((y,e,t)=>
(t=y.indexOf(e),t>=0&&y.splice(t,1),y),[...y]).length
}
console.log(arrayContains([1,2,3], [1,5])) // false - no 5 present
console.log(arrayContains([1,2,3], [1,2])) // true
console.log(arrayContains([1,2,3], [1,2,2])) // false - not enough 2s
console.log(arrayContains([2,1,2,3], [2,2,1])) // true
I want a function that returns true if and only if a given array includes all the elements of a given "target" array. As follows.
const target = [ 1, 2, 3, ];
const array1 = [ 1, 2, 3, ]; // true
const array2 = [ 1, 2, 3, 4, ]; // true
const array3 = [ 1, 2, ]; // false
How can I accomplish the above result?
You can combine the .every() and .includes() methods:
let array1 = [1,2,3],
array2 = [1,2,3,4],
array3 = [1,2];
let checker = (arr, target) => target.every(v => arr.includes(v));
console.log(checker(array2, array1)); // true
console.log(checker(array3, array1)); // false
The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value. Stands to reason that if you call every() on the original array and supply to it a function that checks if every element in the original array is contained in another array, you will get your answer. As such:
const ar1 = ['a', 'b'];
const ar2 = ['c', 'd', 'a', 'z', 'g', 'b'];
if(ar1.every(r => ar2.includes(r))){
console.log('Found all of', ar1, 'in', ar2);
}else{
console.log('Did not find all of', ar1, 'in', ar2);
}
You can try with Array.prototype.every():
The every() method tests whether all elements in the array pass the test implemented by the provided function.
and Array.prototype.includes():
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
var mainArr = [1,2,3];
function isTrue(arr, arr2){
return arr.every(i => arr2.includes(i));
}
console.log(isTrue(mainArr, [1,2,3]));
console.log(isTrue(mainArr, [1,2,3,4]));
console.log(isTrue(mainArr, [1,2]));
I used Purely Javascript.
function checkElementsinArray(fixedArray,inputArray)
{
var fixedArraylen = fixedArray.length;
var inputArraylen = inputArray.length;
if(fixedArraylen<=inputArraylen)
{
for(var i=0;i<fixedArraylen;i++)
{
if(!(inputArray.indexOf(fixedArray[i])>=0))
{
return false;
}
}
}
else
{
return false;
}
return true;
}
console.log(checkElementsinArray([1,2,3], [1,2,3]));
console.log(checkElementsinArray([1,2,3], [1,2,3,4]));
console.log(checkElementsinArray([1,2,3], [1,2]));
If you are using ES5, then you can simply do this.
targetArray =[1,2,3];
array1 = [1,2,3]; //return true
array2 = [1,2,3,4]; //return true
array3 = [1,2] //return false
console.log(targetArray.every(function(val) { return array1.indexOf(val) >= 0; })); //true
console.log(targetArray.every(function(val) { return array2.indexOf(val) >= 0; })); // true
console.log(targetArray.every(function(val) { return array3.indexOf(val) >= 0; }));// false
reduce can be used here as well (but it has O = (N * M) difficulty):
const result = target.reduce((acc, el) => {
return acc && array.includes(el)
}, true);
To solve this in more efficient way(O = N + M):
const myMap = new Map();
array.forEach(element => myMap.set(element);
const result = target.reduce((acc, el) => {
return acc && myMap.has(el)
}, true);
If you're checking if array x contains everything in array y, including requiring multiple occurrences of elements in y to appear multiple times in x:
function arrayContains(x,y) {
// returns true if array x contains all elements in array y
return !x.reduce((y,e,t)=>
(t=y.indexOf(e),t>=0&&y.splice(t,1),y),[...y]).length
}
console.log(arrayContains([1,2,3], [1,5])) // false - no 5 present
console.log(arrayContains([1,2,3], [1,2])) // true
console.log(arrayContains([1,2,3], [1,2,2])) // false - not enough 2s
console.log(arrayContains([2,1,2,3], [2,2,1])) // true
I want a function that returns true if and only if a given array includes all the elements of a given "target" array. As follows.
const target = [ 1, 2, 3, ];
const array1 = [ 1, 2, 3, ]; // true
const array2 = [ 1, 2, 3, 4, ]; // true
const array3 = [ 1, 2, ]; // false
How can I accomplish the above result?
You can combine the .every() and .includes() methods:
let array1 = [1,2,3],
array2 = [1,2,3,4],
array3 = [1,2];
let checker = (arr, target) => target.every(v => arr.includes(v));
console.log(checker(array2, array1)); // true
console.log(checker(array3, array1)); // false
The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value. Stands to reason that if you call every() on the original array and supply to it a function that checks if every element in the original array is contained in another array, you will get your answer. As such:
const ar1 = ['a', 'b'];
const ar2 = ['c', 'd', 'a', 'z', 'g', 'b'];
if(ar1.every(r => ar2.includes(r))){
console.log('Found all of', ar1, 'in', ar2);
}else{
console.log('Did not find all of', ar1, 'in', ar2);
}
You can try with Array.prototype.every():
The every() method tests whether all elements in the array pass the test implemented by the provided function.
and Array.prototype.includes():
The includes() method determines whether an array includes a certain element, returning true or false as appropriate.
var mainArr = [1,2,3];
function isTrue(arr, arr2){
return arr.every(i => arr2.includes(i));
}
console.log(isTrue(mainArr, [1,2,3]));
console.log(isTrue(mainArr, [1,2,3,4]));
console.log(isTrue(mainArr, [1,2]));
I used Purely Javascript.
function checkElementsinArray(fixedArray,inputArray)
{
var fixedArraylen = fixedArray.length;
var inputArraylen = inputArray.length;
if(fixedArraylen<=inputArraylen)
{
for(var i=0;i<fixedArraylen;i++)
{
if(!(inputArray.indexOf(fixedArray[i])>=0))
{
return false;
}
}
}
else
{
return false;
}
return true;
}
console.log(checkElementsinArray([1,2,3], [1,2,3]));
console.log(checkElementsinArray([1,2,3], [1,2,3,4]));
console.log(checkElementsinArray([1,2,3], [1,2]));
If you are using ES5, then you can simply do this.
targetArray =[1,2,3];
array1 = [1,2,3]; //return true
array2 = [1,2,3,4]; //return true
array3 = [1,2] //return false
console.log(targetArray.every(function(val) { return array1.indexOf(val) >= 0; })); //true
console.log(targetArray.every(function(val) { return array2.indexOf(val) >= 0; })); // true
console.log(targetArray.every(function(val) { return array3.indexOf(val) >= 0; }));// false
reduce can be used here as well (but it has O = (N * M) difficulty):
const result = target.reduce((acc, el) => {
return acc && array.includes(el)
}, true);
To solve this in more efficient way(O = N + M):
const myMap = new Map();
array.forEach(element => myMap.set(element);
const result = target.reduce((acc, el) => {
return acc && myMap.has(el)
}, true);
If you're checking if array x contains everything in array y, including requiring multiple occurrences of elements in y to appear multiple times in x:
function arrayContains(x,y) {
// returns true if array x contains all elements in array y
return !x.reduce((y,e,t)=>
(t=y.indexOf(e),t>=0&&y.splice(t,1),y),[...y]).length
}
console.log(arrayContains([1,2,3], [1,5])) // false - no 5 present
console.log(arrayContains([1,2,3], [1,2])) // true
console.log(arrayContains([1,2,3], [1,2,2])) // false - not enough 2s
console.log(arrayContains([2,1,2,3], [2,2,1])) // true
I'm trying to figure out how to compare if certain elements in two arrays compare in the same order.
var compare = function (arr1, arr2) {
//........
}
compare ([f,t,r,m], [s,f,t,r,q,p,m]); //should return true
compare ([f,t,r,m], [f,a,t,,m,r]); //should return false
I proceeded with a for loop and then identifying when the values match, then I'm pretty sure you should compare the arrays but I feel I'm missing something.
var compare = function (a, b) {
a.forEach(function(letter){
for (i=0; i<b.length; i++) {
if (letter===b[i]) {}
}
})
}
Both of these functions will do this comparison with a O(n) runtime, where Ori Drori's solution runs in O(n^2)
var a = [1,2,3];
var b = [0,1,4,3,9,10,2,5,6]; // 1,2,3 in wrong order
var c = [0,4,1,5,6,2,8,3,5]; // 1,2,3 in right order
// using foreach
function compare(a,b){
var i = 0;
b.forEach(function(el){
if(el == a[i]) i++;
})
return i == a.length;
}
// using reduce
function compare2(a,b){
return b.reduce(function(i, el){
return el == a[i] ? i + 1 : i;
}, 0) == a.length;
}
console.log(compare(a,b) == false); // should be false
console.log(compare(a,c) == true); // should be true
console.log(compare2(a,b) == false); // should be false
console.log(compare2(a,c) == true); // should be true
Remove all letters from the 2nd array that don't appear in 1st array using Array#filter and Array#indexOf. Then iterate the result with Array#every, and check if every character appears in the same place in the 1st array:
function compare(a, b) {
var arr = b.filter(function(c) {
return a.indexOf(c) !== -1; // use a hash object instead of indexOf if the arrays are large
});
return arr.every(function(c, i) {
return c === a[i];
});
}
console.log(compare(['f','t','r','m'], ['s','f','t','r','q','p','m'])); //should return true
console.log(compare(['f','t','r','m'], ['f','a','t','m','r'])); //should return false
You could take an index for array2 and check while iterating and return the comparison of the index and array2 and the element of array1.
function compare(array1, array2) {
var i = 0;
return array1.every(function (a) {
while (i < array2.length && a !== array2[i]) {
i++;
}
return a === array2[i++];
});
}
console.log(compare(['f', 't', 'r', 'm'], ['s', 'f', 't', 'r', 'q', 'p', 'm'])); // true
console.log(compare(['f', 't', 'r', 'm'], ['f', 'a', 't', , 'm', 'r'])); // false
You may do as follows;
function compare(a,b){
return b.filter(e => a.includes(e))
.every((e,i) => e === a[i])
}
console.log(compare(["f","t","r","m"], ["s","f","t","r","q","p","m"]));
console.log(compare(["f","t","r","m"], ["f","a","t","m","r"]));
I have two arrays of JavaScript Objects that I'd like to compare to see if they are the same. The objects may not (and most likely will not) be in the same order in each array. Each array shouldn't have any more than 10 objects. I thought jQuery might have an elegant solution to this problem, but I wasn't able to find much online.
I know that a brute nested $.each(array, function(){}) solution could work, but is there any built in function that I'm not aware of?
Thanks.
There is an easy way...
$(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0
If the above returns true, both the arrays are same even if the elements are in different order.
NOTE: This works only for jquery versions < 3.0.0 when using JSON objects
I was also looking for this today and found:
http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD
Don't know if that's a good solution though they do mention some performance considerations taken into account.
I like the idea of a jQuery helper method.
#David I'd rather see your compare method to work like:
jQuery.compare(a, b)
I doesn't make sense to me to be doing:
$(a).compare(b)
where a and b are arrays. Normally when you $(something) you'd be passing a selector string to work with DOM elements.
Also regarding sorting and 'caching' the sorted arrays:
I don't think sorting once at the start of the method instead of every time through the loop is 'caching'. The sort will still happen every time you call compare(b). That's just semantics, but...
for (var i = 0; t[i]; i++) { ...this loop finishes early if your t array contains a false value in it somewhere, so $([1, 2, 3, 4]).compare([1, false, 2, 3]) returns true!
More importantly the array sort() method sorts the array in place, so doing var b = t.sort() ...doesn't create a sorted copy of the original array, it sorts the original array and also assigns a reference to it in b. I don't think the compare method should have side-effects.
It seems what we need to do is to copy the arrays before working on them. The best answer I could find for how to do that in a jQuery way was by none other than John Resig here on SO! What is the most efficient way to deep clone an object in JavaScript? (see comments on his answer for the array version of the object cloning recipe)
In which case I think the code for it would be:
jQuery.extend({
compare: function (arrayA, arrayB) {
if (arrayA.length != arrayB.length) { return false; }
// sort modifies original array
// (which are passed by reference to our method!)
// so clone the arrays before sorting
var a = jQuery.extend(true, [], arrayA);
var b = jQuery.extend(true, [], arrayB);
a.sort();
b.sort();
for (var i = 0, l = a.length; i < l; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
});
var a = [1, 2, 3];
var b = [2, 3, 4];
var c = [3, 4, 2];
jQuery.compare(a, b);
// false
jQuery.compare(b, c);
// true
// c is still unsorted [3, 4, 2]
My approach was quite different - I flattened out both collections using JSON.stringify and used a normal string compare to check for equality.
I.e.
var arr1 = [
{Col: 'a', Val: 1},
{Col: 'b', Val: 2},
{Col: 'c', Val: 3}
];
var arr2 = [
{Col: 'x', Val: 24},
{Col: 'y', Val: 25},
{Col: 'z', Val: 26}
];
if(JSON.stringify(arr1) == JSON.stringify(arr2)){
alert('Collections are equal');
}else{
alert('Collections are not equal');
}
NB: Please note that his method assumes that both Collections are sorted in a similar fashion, if not, it would give you a false result!
Convert both array to string and compare
if (JSON.stringify(array1) == JSON.stringify(array2))
{
// your code here
}
I found this discussion because I needed a way to deep compare arrays and objects. Using the examples here, I came up with the following (broken up into 3 methods for clarity):
jQuery.extend({
compare : function (a,b) {
var obj_str = '[object Object]',
arr_str = '[object Array]',
a_type = Object.prototype.toString.apply(a),
b_type = Object.prototype.toString.apply(b);
if ( a_type !== b_type) { return false; }
else if (a_type === obj_str) {
return $.compareObject(a,b);
}
else if (a_type === arr_str) {
return $.compareArray(a,b);
}
return (a === b);
}
});
jQuery.extend({
compareArray: function (arrayA, arrayB) {
var a,b,i,a_type,b_type;
// References to each other?
if (arrayA === arrayB) { return true;}
if (arrayA.length != arrayB.length) { return false; }
// sort modifies original array
// (which are passed by reference to our method!)
// so clone the arrays before sorting
a = jQuery.extend(true, [], arrayA);
b = jQuery.extend(true, [], arrayB);
a.sort();
b.sort();
for (i = 0, l = a.length; i < l; i+=1) {
a_type = Object.prototype.toString.apply(a[i]);
b_type = Object.prototype.toString.apply(b[i]);
if (a_type !== b_type) {
return false;
}
if ($.compare(a[i],b[i]) === false) {
return false;
}
}
return true;
}
});
jQuery.extend({
compareObject : function(objA,objB) {
var i,a_type,b_type;
// Compare if they are references to each other
if (objA === objB) { return true;}
if (Object.keys(objA).length !== Object.keys(objB).length) { return false;}
for (i in objA) {
if (objA.hasOwnProperty(i)) {
if (typeof objB[i] === 'undefined') {
return false;
}
else {
a_type = Object.prototype.toString.apply(objA[i]);
b_type = Object.prototype.toString.apply(objB[i]);
if (a_type !== b_type) {
return false;
}
}
}
if ($.compare(objA[i],objB[i]) === false){
return false;
}
}
return true;
}
});
Testing
var a={a : {a : 1, b: 2}},
b={a : {a : 1, b: 2}},
c={a : {a : 1, b: 3}},
d=[1,2,3],
e=[2,1,3];
console.debug('a and b = ' + $.compare(a,b)); // a and b = true
console.debug('b and b = ' + $.compare(b,b)); // b and b = true
console.debug('b and c = ' + $.compare(b,c)); // b and c = false
console.debug('c and d = ' + $.compare(c,d)); // c and d = false
console.debug('d and e = ' + $.compare(d,e)); // d and e = true
In my case compared arrays contain only numbers and strings. This solution worked for me:
function are_arrs_equal(arr1, arr2){
return arr1.sort().toString() === arr2.sort().toString()
}
Let's test it!
arr1 = [1, 2, 3, 'nik']
arr2 = ['nik', 3, 1, 2]
arr3 = [1, 2, 5]
console.log (are_arrs_equal(arr1, arr2)) //true
console.log (are_arrs_equal(arr1, arr3)) //false
I don't think there's a good "jQuery " way to do this, but if you need efficiency, map one of the arrays by a certain key (one of the unique object fields), and then do comparison by looping through the other array and comparing against the map, or associative array, you just built.
If efficiency is not an issue, just compare every object in A to every object in B. As long as |A| and |B| are small, you should be okay.
Well, if you want to compare only the contents of arrays, there's a useful jQuery function $.inArray()
var arr = [11, "String #1", 14, "String #2"];
var arr_true = ["String #1", 14, "String #2", 11]; // contents are the same as arr
var arr_false = ["String #1", 14, "String #2", 16]; // contents differ
function test(arr_1, arr_2) {
var equal = arr_1.length == arr_2.length; // if array sizes mismatches, then we assume, that they are not equal
if (equal) {
$.each(arr_1, function (foo, val) {
if (!equal) return false;
if ($.inArray(val, arr_2) == -1) {
equal = false;
} else {
equal = true;
}
});
}
return equal;
}
alert('Array contents are the same? ' + test(arr, arr_true)); //- returns true
alert('Array contents are the same? ' + test(arr, arr_false)); //- returns false
Change array to string and compare
var arr = [1,2,3],
arr2 = [1,2,3];
console.log(arr.toString() === arr2.toString());
The nice one liner from Sudhakar R as jQuery global method.
/**
* Compare two arrays if they are equal even if they have different order.
*
* #link https://stackoverflow.com/a/7726509
*/
jQuery.extend({
/**
* #param {array} a
* First array to compare.
* #param {array} b
* Second array to compare.
* #return {boolean}
* True if both arrays are equal, otherwise false.
*/
arrayCompare: function (a, b) {
return $(a).not(b).get().length === 0 && $(b).not(a).get().length === 0;
}
});
I also found this when looking to do some array comparisons with jQuery. In my case I had strings which I knew to be arrays:
var needle = 'apple orange';
var haystack = 'kiwi orange banana apple plum';
But I cared if it was a complete match or only a partial match, so I used something like the following, based off of Sudhakar R's answer:
function compareStrings( needle, haystack ){
var needleArr = needle.split(" "),
haystackArr = haystack.split(" "),
compare = $(haystackArr).not(needleArr).get().length;
if( compare == 0 ){
return 'all';
} else if ( compare == haystackArr.length ) {
return 'none';
} else {
return 'partial';
}
}
If duplicates matter such that [1, 1, 2] should not be equal to [2, 1] but should equal [1, 2, 1], here is a reference counting solution:
const arrayContentsEqual = (arrayA, arrayB) => {
if (arrayA.length !== arrayB.length) {
return false}
const refCount = (function() {
const refCountMap = {};
const refCountFn = (elt, count) => {
refCountMap[elt] = (refCountMap[elt] || 0) + count}
refCountFn.isZero = () => {
for (let elt in refCountMap) {
if (refCountMap[elt] !== 0) {
return false}}
return true}
return refCountFn})()
arrayB.map(eltB => refCount(eltB, 1));
arrayA.map(eltA => refCount(eltA, -1));
return refCount.isZero()}
Here is the fiddle to play with.
var arr1 = [
{name: 'a', Val: 1},
{name: 'b', Val: 2},
{name: 'c', Val: 3}
];
var arr2 = [
{name: 'c', Val: 3},
{name: 'x', Val: 4},
{name: 'y', Val: 5},
{name: 'z', Val: 6}
];
var _isEqual = _.intersectionWith(arr1, arr2, _.isEqual);// common in both array
var _difference1 = _.differenceWith(arr1, arr2, _.isEqual);//difference from array1
var _difference2 = _.differenceWith(arr2, arr1, _.isEqual);//difference from array2
console.log(_isEqual);// common in both array
console.log(_difference1);//difference from array1
console.log(_difference2);//difference from array2
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
Try this
function check(c,d){
var a = c, b = d,flg = 0;
if(a.length == b.length)
{
for(var i=0;i<a.length;i++)
a[i] != b[i] ? flg++ : 0;
}
else
{
flg = 1;
}
return flg = 0;
}