Is it possible to get the difference of an associative array and a regular array in Javascript?
Ex.
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?
Ex.
array1 = [5, 1, 3];
array2 = [1 => 15, 2 => 20, 3 => 10, 4 => 5, 5 =>50 ];
The difference would be...
diff = [2 => 20, 4=> 5];
I 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));
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 commenters 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 come 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.