1

I am trying to understand why in nodejs array splice does not work on an associate array.

var a = [];

a['x1'] = 234234;
a['x2'] = 565464;

console.log("Init-------");
showIt();

a.splice(0, 1);
console.log("After splice-------");
showIt();

delete a['x1'];
console.log("After delete-------");
showIt();

function showIt(){
    var keys = Object.keys(a);
    var len  = keys.length;
    var i=0;
    while (i < len) {
        console.log( '    ' + i +  ' ------------ ' + keys[i] );
        i++;
    }
}

Results:

Init-------
        0 ------------ x1
        1 ------------ x2
After splice-------
        0 ------------ x1
        1 ------------ x2
After delete-------
        0 ------------ x2

Splicing the array does nothing...

Same results in a browser...

Update:

Splice works as expected when the array is defined as:

var a = ['x1','x2','x3'];
console.log("Init-------");
console.log(a);

a.splice('x1', 1);
console.log("After splice-------");
console.log(a);

Looks like in the first example, the array is being treated as if is was defined as a object {} in the 2nd, it's being treated more like an array.

To the Moderators:

This is not really a question about spare arrays, it is more of a question of an array which is starting at 0 and growing sequentially to 10 million over a period of days. As it is growing the array is being deleted from so that around 1000 items are in the array at one time.

I am considering forcing the use of hash tables by using non-numeric keys or defining as a object {} so that the it acts like a sparse array.

In the end, I am not sure if it matters...

Brian McGinity
  • 5,777
  • 5
  • 36
  • 46
  • [`splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) works on `arrays` or `array-like` objects, in the first example it is doing exactly what is expected of it [as per spec](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.12) In the second you are [`delet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete)ing a property from an object (an array is still an object) – Xotic750 Feb 20 '14 at 02:10
  • I am starting to see it. Do you see problems with sparse arrays? – Brian McGinity Feb 20 '14 at 02:12
  • Personally no, but why are your arrays sparse, how are you creating them that causes this? – Xotic750 Feb 20 '14 at 02:14
  • In some cases I need to map irregular ids to an object and I want fast access to it using this notation: `myarray[crazyId]` in the case with nodejs which I am researching now I need to maintain an array of websocket connections. The index will start at 0 and increase with each new connection and when the connection is dropped , it is removed from the array. I am worried that v8 might keep the deleted array items in memory and cause a leak. – Brian McGinity Feb 20 '14 at 02:20
  • If the reference is a numerically indexed element in an array that points to a port object, when you `splice` to delete it then that array no longer holds a reference to it. here will be no leak there. That doesn't mean to say that you are not holding some other reference to the port object somewhere else in your code. The only limit with the array is that the indexes are from 0 to 2^32-1. And ofcourse binding more than one connection to a single port number may need a little more thinking. – Xotic750 Feb 20 '14 at 02:25
  • 1
    Of course there is nothing wrong with using a true `Object` with properties and using `delete` to remove them either. – Xotic750 Feb 20 '14 at 02:28
  • With numeric keys that is..splice will work. Yet after a few days of non-stop running, the array length will be 3 million and there will only be 1000 active connections. Does having a mostly empty array cause a leak? – Brian McGinity Feb 20 '14 at 02:29
  • No, not at all. Javascript arrays use an efficient algorithm. I would find you a reference, but I'm sure with a little googling or even a search here will give you that information. – Xotic750 Feb 20 '14 at 02:33
  • http://stackoverflow.com/questions/4524067/if-i-set-only-a-high-index-in-an-array-does-it-waste-memory – Xotic750 Feb 20 '14 at 02:35
  • @Xotic750: You have very good points, but remember that whether sparse arrays perform well is totally up to the implementation. – rvighne Feb 20 '14 at 02:38
  • I don't think you will find any issue with V8 that node is using. But you could quite happily use either method. And how performant does it need to be when regestering or deregestering a connection? – Xotic750 Feb 20 '14 at 02:39
  • 2
    Thanks for your help, I think I am going to make them an object as var connections={} and then use delete. – Brian McGinity Feb 20 '14 at 02:55
  • @BrianMcGinity: Excellent choice. It's the type of thing objects are meant for. – rvighne Feb 20 '14 at 03:49

1 Answers1

1

In JavaScript there is no such thing as an associative array -- there are arrays (like normal arrays in other languages) and objects (like assoc. arrays in other languages). In your example a is a normal array but you set non-numerical keys on it, so the normal array methods (like splice) do not see it. They only look in the range 0...a.length.

Making a an object won't help; it is not possible to splice an object. Try using only numerical keys ([1] instead of ['x1']).

rvighne
  • 20,755
  • 11
  • 51
  • 73
  • [`splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) does indeed mutate the array and then returns `An array containing the removed elements. If only one element is removed, an array of one element is returned. If no elements are removed, an empty array is returned.` – Xotic750 Feb 20 '14 at 01:48
  • Not 100% accurate... With numeric keys, the result of splice is an array of what was removed and the original array is mutated...changed...reduced. With non-numeric keys, the array is being treated like a object. – Brian McGinity Feb 20 '14 at 01:49
  • Also, I do not want to use numeric keys in this case...the other possibility is a vastly sparse numeric array. – Brian McGinity Feb 20 '14 at 01:52
  • What's the problem with `sparse` arrays? And of course you could write you own `splice` that works with objects that are using your index methods ie `x#`. – Xotic750 Feb 20 '14 at 01:58
  • I don't know, I struggle with space arrays vs string keyed arrays. Each of which make the browser use hash mapping functions and each have messed up length properties. I can't figure out which is better :) As for a my own splice function the `delete array[key]` is working well. – Brian McGinity Feb 20 '14 at 02:09
  • Of course [`splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) does far more than simply [`delete`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete) – Xotic750 Feb 20 '14 at 02:12
  • @BrianMcGinity: If you are only using `splice` to delete single elements, then just use a real object, and then use `delete a[key]`, to delete elements. This is also waaaay faster than an array where deleting elements leaves "holes", unlike for objects. – rvighne Feb 20 '14 at 02:21