Odward
Odward

Reputation: 113

Get the lower integer id not already used in Javascript

I have a list of JS objects defined by an integer ID.

objects = [{
    id: 0,
    type: 'null'
}, {
    id: 1,
    type: 'foo'
}, {
    id: 2,
    type: 'bar'
}];

I implemented a function to remove an element from my list :

removeObject = function(o){
    objects.splice(objects.indexOf(o), 1);
}

My problem is that I need to create a function to add a new item in my list with a id not already used (for example the lower positive integer not present in the list).

I tried to do something like that but it did not work when I remove the object 0 (for example).

addObject = function(type){
    objects.push({
        id: objects.length,
        type: type
    });
};

How can I do this ?

EDIT 1

According to your answers, I assume that the best solution in term of performance is to just use a topId which is always incremented when I add a new object in my list.

But that do not answer to my requierement. Actually I think that @X-Pippes response could be good.

Should I do someting like that :

objects = [{
    id: 0,
    type: 'null'
}, {
    id: 1,
    type: 'foo'
}, {
    id: 2,
    type: 'bar'
}];

// Init available ids list with the default value
availableIds = [objects.length];

removeObject = function(o){
    // Remove the object from the list
    objects.splice(objects.indexOf(o), 1);
    // Add its id to the available ids list
    availableIds.push(o.id);
}

addObject = function(type){
    // Get lower id available
    var newId = Math.min.apply(Math,availableIds);
    // Push the new object with the id retrieved
    objects.push({
        id: newId,
        type: type
    });
    // Remove used id from the available ids list
    availableIds.splice(availableIds.indexOf(newId), 1);
    // Add a default id if available list is empty
    if(availableIds.length < 1) availableIds.push(objects.length);
};

Upvotes: 0

Views: 162

Answers (5)

technosaurus
technosaurus

Reputation: 7802

You can and probably should just use an array(s) like:

objects.type=['null','foo','bar'];

to add an object see: How to append something to an array?

to find a value: var index = objects.type.indexOf('foo');

to find 1st empty field var index = objects.type.indexOf(''); which you can use to find the element for adding (if index is -1 use objects.type.length) if you "delete" an element by setting it to "" or... unless you have specific reason for keeping the "ID" static (in this case the array index), remove the element and only append new ones to the end

to remove an element see: How do I remove a particular element from an array in JavaScript? which will allow you to just push/append the next data.

if you need a new object array with empty fields to fill because you get new data to track:

object.newField=new Array(objects.type.length);

If you get to this point where your object contains multiple arrays, you will probably want to create functions for insert/add and delete/remove, so you don't do an operation on 1 and not the other.

Everything is already built in (read likely already pretty fast) and you don't need to reinvent constructors for your really cool object type.

Upvotes: 0

exebook
exebook

Reputation: 33900

In Javascript MaxInt is 9007199254740992. Why not just keep incrementing?

Upvotes: 0

Joe
Joe

Reputation: 47619

Use the correct structures. A JavaScript object will do the job. It guarantees that you only get one item for key, you can look up and remove by key in probably O(1)ish. No point trying to re-implement it in a less efficient manner, which will be O(n) lookup.

var structure = {
    objects : {},
    topId : 0
}

structure.add = function(item) {
    var id = this.topId ++;

    structure.objects[id] = item;
}

structure.add("thing")
structure.add("other thing")
structure.add("another thing")

structure.objects
>>> Object {0: "thing", 1: "other thing", 2: "another thing"}

structure.objects[1]
>> "other thing"

Then the normal index operations to get/set/delete.

If you use that function then you have an invariant (guarantee) on your data structure that you won't use the same ID twice.

Upvotes: 1

Jaime Torres
Jaime Torres

Reputation: 10515

You need a function to find the first free number:

addObject = function(type){
    objects.push({
        id: firstOpenIndex(),
        type: type
    });
};

firstOpenIndex = function() {
    for(var idx = 0; true; i++) {
       var found = false;
       for(var o in objects) {
          if (objects[o].id == idx) {
             found = true;
             break;
          }
       }
       if (!found) return idx;
    }
}

Upvotes: 0

X-Pippes
X-Pippes

Reputation: 1170

if you remove for instance 0 and the next addObject is 0 you have to do something like:

  • keep a list [initial empty] with every ID removed. When you need to add a new one, pick the shorter, add and delete from list.
  • Also keep a var with the biggest ID added. If the previous list is empty, add +1 to the var and addObject with that id

Upvotes: 1

Related Questions