最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How do I get the difference between an associative array and a regular array in JavaScript? - Stack Overflow

programmeradmin2浏览0评论

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 values 15, 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
Add a ment  | 

4 Answers 4

Reset to default 4

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));

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.

发布评论

评论列表(0)

  1. 暂无评论