获取Javascript中尚未使用的较低整数id
我有一个由整数ID定义的JS对象列表获取Javascript中尚未使用的较低整数id,javascript,Javascript,我有一个由整数ID定义的JS对象列表 objects = [{ id: 0, type: 'null' }, { id: 1, type: 'foo' }, { id: 2, type: 'bar' }]; 我实现了一个从列表中删除元素的函数: removeObject = function(o){ objects.splice(objects.indexOf(o), 1); } 我的问题是,我需要创建一个函数,在列表中添加一个id尚未
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
我实现了一个从列表中删除元素的函数:
removeObject = function(o){
objects.splice(objects.indexOf(o), 1);
}
我的问题是,我需要创建一个函数,在列表中添加一个id尚未使用的新项(例如,列表中不存在较低的正整数)
我试图做类似的事情,但当我删除对象0(例如)时,它不起作用
我该怎么做
编辑1
根据您的回答,我假设性能方面的最佳解决方案是只使用topId,当我在列表中添加新对象时,topId总是递增的
但这不符合我的要求。事实上,我认为@X-Pippes的反应可能是好的
我应该这样做吗:
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);
};
对象=[{
id:0,
类型:“null”
}, {
id:1,
类型:“foo”
}, {
id:2,
类型:'bar'
}];
//使用默认值初始化可用ID列表
availableIds=[objects.length];
removeObject=函数(o){
//从列表中删除该对象
对象.拼接(对象.索引of(o),1);
//将其id添加到可用id列表中
可用推送(o.id);
}
addObject=函数(类型){
//获取可用的较低id
var newId=Math.min.apply(Math,availableIds);
//使用检索到的id推送新对象
objects.push({
id:newId,
类型:类型
});
//从可用id列表中删除已用id
拼接(availableIds.indexOf(newId),1);
//如果可用列表为空,请添加默认id
if(availableIds.length<1)availableIds.push(objects.length);
};
使用正确的结构。JavaScript对象
将完成这项工作。它保证您只获得一项密钥,您可以在O(1)ish中按密钥查找和删除。没有必要尝试以效率较低的方式重新实现它,这将是O(n)查找
然后执行常规索引操作以获取/设置/删除
如果您使用该函数,那么您的数据结构上就有一个不变量(保证),您不会两次使用相同的ID 如果删除实例0,而下一个addObject为0,则必须执行以下操作:
- 保留一个删除每个ID的列表[初始值为空]。当您需要添加新的时,选择较短的,从列表中添加和删除
- 还保留一个添加了最大ID的var。如果上一个列表为空,则将+1添加到var并使用该id添加对象
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;
}
}
在Javascript中,MaxInt是9007199254740992。为什么不继续递增呢?您可以而且可能应该使用如下数组:
objects.type=['null','foo','bar']代码>
要添加对象,请参见:
要查找值:var index=objects.type.indexOf('foo')代码>
查找第一个空字段var index=objects.type.indexOf(“”)代码>如果通过将某个元素设置为“”或“”来“删除”该元素,则可以使用它来查找要添加的元素(如果索引为-1,则使用objects.type.length)。。。除非您有特定的理由保持“ID”为静态(在本例中为数组索引),否则请删除该元素并仅在末尾追加新的元素
要删除图元,请参见:
这将允许您只需推送/附加下一个数据
如果因为要跟踪新数据而需要填充带有空字段的新对象数组,请执行以下操作:
object.newField=新数组(objects.type.length)代码>
如果您的对象包含多个数组,那么您可能需要创建用于插入/添加和删除/删除的函数,这样您就不会对1执行操作,而不会对另一个执行操作
所有内容都已内置(读取速度可能已经相当快),您不需要为真正酷的对象类型重新创建构造函数。如果删除实例0,下一个addObject应该是id=0?为什么不简单地跟踪上次使用的id和增量?为什么要使用数组而不是映射呢?使用数组并跟踪在删除项目而不是每个项目的id时移动的索引是不可能的吗?对于最佳解决方案,数组、hashmap等。这将取决于从列表中逐出项的频率以及您需要的其他操作。因此,为什么不删除整个id并只使用数组。。。它已经被索引。。。typeObjects=[“null”、“foo”、“bar”]可以在编辑1:)中自由分享有关解决方案性能的任何反馈。这将如何解决查找编号最低的“id”值以存储新条目的问题?以及删除structure.objects[1]并转到“添加”时会发生什么情况?OP希望下一个项目进入结构。对象[1]而不是下一个最高的索引。这并不能解决问题,因为项目将被删除(removeObject
在Q中的函数)。我知道问题是什么,但值得重新思考实际需求,它可能会与实现细节混淆。这几乎肯定满足了最初的要求。数字很便宜。正如exebook所说,计数器会达到maxint吗?@Joe-工作正常,但几乎完全复制了一个数组,缺少类似数组的内置函数。topId~=length add~=push,…什么是打开的
?像这样的事情似乎是显而易见的、微不足道的解决方案。当没有间隙时,它将导致O(n)最坏情况。一个输入错误——它应该是idx。我同意这是显而易见的/微不足道的,但这正是OP所要求的。如果要用最小数值来填充第一个可用的间隙,则需要O(n^2)。这可以通过不同的数据结构来提高效率,但如果您想维护OP提出的需求,则不能这样做。实际上,这是O(n^2)最坏的情况。找到第一个空字段将是O(n),这可能会变得非常大(对于任何实现都是如此)。或者,如果您只想使用topId,那么最终将在一个稀疏数组中出现“洞”,并不断增长
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"
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;
}
}