Is it possible to get the difference of an associative array and a regular array in JavaScript?
Example
array1 = [5, 1, 3];
array2 = [1 => 15, 2 => 20, 3 => 10, 4 => 5, 5 =>50 ];
The difference would be...
diff = [2 => 20, 4=> 5];
Is it possible to get the difference of an associative array and a regular array in JavaScript?
Example
array1 = [5, 1, 3];
array2 = [1 => 15, 2 => 20, 3 => 10, 4 => 5, 5 =>50 ];
The difference would be...
diff = [2 => 20, 4=> 5];
Share
Improve this question
edited Jun 1, 2024 at 22:49
Peter Mortensen
31.6k22 gold badges110 silver badges133 bronze badges
asked Jul 9, 2012 at 0:19
JohnSmithJohnSmith
1,5572 gold badges18 silver badges27 bronze badges
4
- 5 Your second array should be an object, not an array (JavaScript doesn't have associative arrays as such). And indeed, pasting the above into the JavaScript console in Chrome reports: "SyntaxError: Unexpected token >" Further: potential dupe, at: stackoverflow./questions/1187518/javascript-array-difference – David Thomas Commented Jul 9, 2012 at 0:21
- Your second array isn't valid JavaScript. – Brandon J. Boone Commented Jul 9, 2012 at 0:22
- Do you mean the second array should be like... array2[1] = 15? – JohnSmith Commented Jul 9, 2012 at 0:25
-
If I understand this correctly, the
diff
should deliver only those values that are contained in array2, but not in array1. However, array2 has the values15, 20, 10, 5, 50
, thus the diff would have to be[15, 20, 10, 50]
, since 1 and 3 are only keys of array2. Kudos for messing up JS object notation with Perl hash notation, though, happens to me all of the time, when I'm doing both within a short stretch of time or switching back and forth. – yogibimbi Commented Apr 15, 2013 at 19:49
4 Answers
Reset to default 4I assume your question just had a small typo in your declaration of array2
. This is not a big deal.
Anyway, here is a bit of hack, but it gives you what you want:
array1 = [5, 1, 3];
array2 = {1: 15, 2: 20, 3: 10, 4: 5, 5: 50};
var result = {};
for (var i in array2) {
if (array1.indexOf(+i) < 0) {
result[i] = array2[i];
}
}
alert(JSON.stringify(result));
Working example
My hack is the +i
in the indexOf
call, because the properties of your "associative array" are strings, but your array1
contains numbers. The unary +
produces a number from a string. Kind of hackish but it is idiomatic an accepted JavaScript practice.
ADDENDUM
As RobG points out, indexOf
is an ES5 method, so if your JavaScript engine is ES3 or below, you will need to implement indexOf
on your own. An example of how to do this is at MDN. Alternatively, you can just do the equivalent of indexOf
by searching the array on your own.
First of all, your second array should be an object and isn't valid JavaScript, as the first two menters said. Here it is in object form:
var object = { "1": 15, "2": 20, "3": 10, "4": 5, "5": 50 };
This function achieves your desired result:
function findDiff(arr, obj)
{
var tempObj = clone(obj);
for (var i = 0; i < arr.length; i++)
{
var propId = arr[i];
if (tempObj[propId] !== undefined)
delete tempObj[propId];
}
return tempObj;
}
This function relies on a function called clone
, which makes sure obj
is copied to tempObj
by value rather than reference. This prevents the passed object from being modified:
function clone(obj){
if(obj == null || typeof(obj) != 'object')
return obj;
var temp = obj.constructor(); // changed
for(var key in obj)
temp[key] = clone(obj[key]);
return temp;
}
Just call it like this:
var array = [5, 1, 3];
var object = { "1": 15, "2": 20, "3": 10, "4": 5, "5": 50 };
var diff = findDiff(array, object);
You will need to explain in detail what you expect the result of the operation to be.
One interpretation is to remove members from one array based on the values in another, so given:
array1 = [5, 1, 3];
array2 = [15, 20, 10, 5, 50 ];
You might have a function:
function diff(arr1, arr2) {
// Copy arrays so don't affect originals
var t1 = arr1.slice();
var t2 = arr2.slice();
// sort t1
t1.sort();
// Remove members of arr2 from highest indexes to lowest
var i = t1.length;
while (i--) {
t2.splice(t1[i], 1);
}
return t2;
}
alert(diff(array1, array2)); // 15, 10, 50
Note that arrays are zero indexed and there is no 5th member in array2, so the removed values are 20 and 5 (i.e. members with index 1 and 3 respectively).
Another option would be, to do a JSON.stringify()
on your variable and check the leftmost or rightmost character of the resulting string. If it is {
or }
, you have an associative array / object, if [
or ]
, it is an array. Which I imagine might be a bit costly, depending on the size of your array, but it would do the job.
However... since there is no such thing as a free lunch, and all animals e in pairs, this is only a reasonable solution, if you have used your variable consequently according to your original definition.
If you defined an object, like so: obj = [1,2,3]
and then, at a later point, added a value such as obj['w'] = 'ww'
, a JSON.stringify(obj)
would only produce [1,2,3]
, but if you addressed obj['w']
again, you would still get ww
, meaning that the value is not forgotten, they just don't mix. Internally, I would imagine, that javascript keeps two separate variable tables, one for objects and one for arrays, and whichever has been defined first, gets the nod when printed with stringify.
And to confuse things still more, if you define a variable as object first, but then add an array key, aka
obj = {1: 11, 2: 22, 3: 33};
obj[4] = 44;
the new key is automatically cast as a string, thus yielding a result in stringify of
{"1":11, "2": 22, "3": 33, "4": 44} //sans the \", for better readibility
Confusing as hell, but I guess that's the price you pay for a little anarchy and ease of use.