Associate Array splice does not work
Asked Answered
U

1

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...

Unitary answered 20/2, 2014 at 1:21 Comment(13)
splice works on arrays or array-like objects, in the first example it is doing exactly what is expected of it as per spec In the second you are deleting a property from an object (an array is still an object)Kayser
I am starting to see it. Do you see problems with sparse arrays?Unitary
Personally no, but why are your arrays sparse, how are you creating them that causes this?Kayser
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.Unitary
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.Kayser
Of course there is nothing wrong with using a true Object with properties and using delete to remove them either.Kayser
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?Unitary
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.Kayser
#4524567Kayser
@Xotic750: You have very good points, but remember that whether sparse arrays perform well is totally up to the implementation.Concordant
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?Kayser
Thanks for your help, I think I am going to make them an object as var connections={} and then use delete.Unitary
@BrianMcGinity: Excellent choice. It's the type of thing objects are meant for.Concordant
C
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']).

Concordant answered 20/2, 2014 at 1:27 Comment(7)
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.Kayser
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.Unitary
Also, I do not want to use numeric keys in this case...the other possibility is a vastly sparse numeric array.Unitary
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#.Kayser
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.Unitary
Of course splice does far more than simply deleteKayser
@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.Concordant

© 2022 - 2024 — McMap. All rights reserved.