19

I have two JavaScript arrays (A and B) that contain objects that I created. I want to check that all the objects in array A are contained in array B, but not necessarily in the same order.

What is the best way to do this?

Edit:

They are all actual objects, not primitives, so I will need to compare their contents and structure as well (maybe using something like JSON.stringify).

I want to do this because I'm learning Test-Driven Development, and I want to test functions that return lists of objects. I need to test whether the returned lists have the expected objects in them or not (order doesn't matter in this case).

7
  • 2
    Are they primitives such as true, false, 23 or actual objects? Also can you explain why you want to do this? There may be a better way. Commented Jul 14, 2010 at 3:54
  • Edited question for clarification. Commented Jul 14, 2010 at 4:04
  • Why not first sort and then use JSON.stringify to compare Commented Jul 14, 2010 at 4:07
  • Actually you can compare objects by reference. Commented Jul 14, 2010 at 4:08
  • How complex are these objects you're comparing? Do they have characteristics you're going to need to check as well (methods, etc)? Commented Jul 14, 2010 at 4:30

6 Answers 6

5

With ES6 you could use every and some (and length).

let A = [1, 2, 3]; let B = [2, 3, 1]; // all objects in A are contained in B (A ⊆ B) // you can compare a <-> b however you'd like (here just `a === b`) let AsubB = A.every(a => B.some(b => a === b)); // A and B are the same length let sameLength = A.length === B.length; // their contents are as equal as previously tested: let equal = AsubB && sameLength; 
Sign up to request clarification or add additional context in comments.

2 Comments

Checking for containment, even when you use both directions, does not account for multiple equal elements; e.g., consider [1,2,3,3] and [1,2,2,3].
for checking two object properties it's fine; moreover in the question is not requested to check for repeats. I used it with an object containing dates from and to and works nice.
3

Usage: isEqArrays(arr1, arr2)

// // Array comparsion // function inArray(array, el) { for ( var i = array.length; i--; ) { if ( array[i] === el ) return true; } return false; } function isEqArrays(arr1, arr2) { if ( arr1.length !== arr2.length ) { return false; } for ( var i = arr1.length; i--; ) { if ( !inArray( arr2, arr1[i] ) ) { return false; } } return true; } 

3 Comments

Is this faster than @ChaosPandion's solution?
it's cross browser. Chaos's isn't. He uses language features which are not well-supported yet.
This code doesn't work: isEqArrays([0, 0, 1], [0, 1, 1]) returns true.
2

This is probably the simplest method if not the slowest.

var o = { PropA: 1, PropB: 2 }; var a = [1, 2, 3, 4, o]; var b = [2, 3, 4, 1]; var c = a.filter(function(value, index, obj) { return b.indexOf(value) > -1; }); if (c.length !== a.length) { throw new Error("Array b is missing some elements!"); } 

indexOf will only check that they refer to the same object. If you want to check value equivalence you will have to do a deep compare of the properties or use JSON.stringify as you mention in your question.

2 Comments

Does .indexOf check for object equivalency too? As in, if I make an o2 = { PropA: 2, PropB: 2} and put it in b, would it return something other than -1?
As with the other answer, this returns a false positive for [0, 1, 1] and [0, 0, 1].
1

developing/writing code block is fine and this needs deep comparision. but as a developer, we don't need to write code from scratch. we have plenty of options. We are also having a huge npm packages to get the job done specifically developed for these use case. I have used similar-js" it did the job that you need. It extends so many use cases as well.

https://www.npmjs.com/package/similar-js

npm i similar-js

import {isSimilar} from 'similar-js'; const a = [ { id: 0, name: "Ashley Lyons", }, { id: 1, name: "Ophelia Erickson", }, { id: 2, name: "Britney Cook", }, ] const b = [ { id: 2, name: "Britney Cook", }, { id: 0, name: "Ashley Lyons", }, { id: 1, name: "Ophelia Erickson", }, ] console.log(isSimilar(a, b)) 

(Disclosure: I am the owner of the linked repo)

Comments

0

Simple & Elegant

function isEqual(arr1, arr2) { if (arr1.length !== arr2.length) return false; return arr1.every(x => arr2.includes(x)); } 

If duplication is important, use this

function isEqual(arr1, arr2) { if (arr1.length !== arr2.length) return false; arr1.sort(); arr2.sort(); for (var i = 0; i < arr1.length; i++) { if (arr1[i] !== arr2[i]) return false; } return true; } 

1 Comment

isEqual([0, 1, 1], [0, 0, 1]) returns true...
0

Hi it seem more difficult than I thought and I need to code it myself. Please check my solution:

//usage const arr1 = [{ a: 1, b: 2 }, { a: 2, b: 1 }, { a: 1, b: 2, c: 3 }, ]; const arr2 = [{ a: 1, b: 2, c: 3 }, { a: 1, b: 2 }, { a: 2, b: 1 }, ]; alert(compareTwoArray(arr1, arr2)); function compareTwoArray(arr1, arr2) { if (arr1.length != arr2.length || arr1.length == arr2.length == 0) { return false; } //clone arr to process let arr01 = JSON.parse(JSON.stringify(arr1)); let arr02 = JSON.parse(JSON.stringify(arr2)); for (let i = (arr01.length - 1); i >= 0; i--) { for (let j = (arr02.length - 1); j >= 0; j--) { if (JSON.stringify(arr01[i]) === JSON.stringify(arr02[j])) { arr01.splice(i, 1); arr02.splice(j, 1); } } } if (arr01.length == 0 && arr02.length == 0) { return true; } else { return false; } }

This is for array of values only:

//usage alert(compareTwoArray([0, 0, 1, 1], [1, 0, 1, 0])); function compareTwoArray(arr1, arr2) { if (arr1.length != arr2.length || arr1.length == arr2.length == 0) { return false; } //clone arr to process let arr01 = JSON.parse(JSON.stringify(arr1)); let arr02 = JSON.parse(JSON.stringify(arr2)); for (let i = (arr01.length - 1); i >= 0; i--) { for (let j = (arr01.length - 1); j >= 0; j--) { if (arr01[i] == arr02[j]) { //remove duplicate item from both array arr01.splice(i, 1); arr02.splice(j, 1); } } } if (arr01.length == 0 && arr02.length == 0) { return true; } else { return false; } }

5 Comments

is it working with actual objects, not primitives?
@MarcC I think you need to add code to compare two object instead of if (arr01[i] == arr02[j]) and then it can be work on arrays of objects
The question mentioned object comparison so your solution does not answer the question. You have to consider nested objects as well (ie. a tree of objects).
@MarcC oh right! I just updated my answer for arrays of objects
Good, your approach is generating a lot of new objects and strings but is doing the job. I would have opted for a recursive in-place comparison.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.