存储严格索引数组的javascript/json

存储严格索引数组的javascript/json,javascript,arrays,json,Javascript,Arrays,Json,我试图用javascript描述一个口袋妖怪移动“数据库”来练习数据描述 我有一系列动作,由id(数字)、名称(字符串)和类型(字符串)标识 我想创建这样一个移动的javascript数组(使用数组索引作为id进行O(1)按id查找): 但是,我希望确保这些条目的索引是严格定位的(以避免将条目粘贴到数组的开头,使索引无效,并使其更明确地显示条目的内容,这样您就不需要在每次查看列表时进行线性搜索来查找条目) 我想做的是这样,但JavaScript语法不支持: const moves = [

我试图用javascript描述一个口袋妖怪移动“数据库”来练习数据描述

我有一系列动作,由id(数字)、名称(字符串)和类型(字符串)标识

我想创建这样一个移动的javascript数组(使用数组索引作为id进行O(1)按id查找):

但是,我希望确保这些条目的索引是严格定位的(以避免将条目粘贴到数组的开头,使索引无效,并使其更明确地显示条目的内容,这样您就不需要在每次查看列表时进行线性搜索来查找条目)

我想做的是这样,但JavaScript语法不支持:

const moves = [
    0: {name: 'Astonish', type: 'Ghost'},
    1: {name: 'Constrict', type: 'Normal'},
    2: {name: 'Acid', type: 'Poison'},
    3: {name: 'Ingrain', type: 'Grass'}
];
通过显式插入每个项目来执行此操作似乎很昂贵,而且在视觉上很烦人:

const moves = [];

/* anonymous scope: setup moves */
{
    moves[0] = {name: 'Astonish', type: 'Ghost'};
    moves[1] = {name: 'Constrict', type: 'Normal'},
    moves[2] = {name: 'Acid', type: 'Poison'},
    moves[3] = {name: 'Ingrain', type: 'Grass'}
}
我可以使用对象,但对于这种行为,对象比数组更昂贵。我也可以创建一个对象,然后将其映射到如下数组:

const moves = (() => {
    let res = [];
    let tmp = {
        0: {name: 'Astonish', type: 'Ghost'},
        1: {name: 'Constrict', type: 'Normal'},
        2: {name: 'Acid', type: 'Poison'},
        3: {name: 'Ingrain', type: 'Grass'}
    };
    Object.keys(tmp).map ((key) => {
        res[key] = tmp[key];            
    });

    return res;
})();
但这似乎有点傻

我希望将数组索引作为id的原因是,它既可以快速访问,又可以方便地使另一个对象将移动名称映射回其id(对于O(1)按名称移动查找)

有没有一种方法可以更连贯地描述这种数组,或者这些是我唯一没有发明自己的javascript约定的选项,即预处理器

提前谢谢

相关的


JavaScript中的数组保留了顺序。您的第一个解决方案是最简单、最优雅的,应该可以完美地工作

还请注意,对象不保证其名称/值对的顺序

你可以做一些类似的事情:

let tmp = [
    {"0": {name: 'Astonish', type: 'Ghost'}},
    {"1": {name: 'Constrict', type: 'Normal'}},
    {"2": {name: 'Acid', type: 'Poison'}},
    {"3": {name: 'Ingrain', type: 'Grass'}}
];

但我认为这不值得

还有更多的缺点:

  • 如果移动ID是由其数组索引隐式给出的(并且您希望将数组保持为普通线性存储阵列),则不允许在ID范围内存在“孔”,而不浪费空间
  • 如果删除移动,则必须对不再在O(1)中的阵列(假设为线性存储阵列)进行切片,并移动所有后续ID
  • 如果您允许ID范围中存在间隙,例如通过插入
    移动[3]=…;移动[5]=…;
    或删除数组条目,您的数组可能会“降级”,即不再是线性存储数组,而是映射

为了避免所有这些问题,并且仍然具有O(1)comp.复杂性(除非您的JS引擎非常古怪)对于插入、访问和删除,请使用映射。ES6
map
或一个普通的旧
对象

您的问题中有一大堆错误的假设和语法错误。长话短说,只需使用您开始使用的简单数组即可-非常完美。您能说出我使用的语法吗?我测试了代码,它看起来非常完美ine..您不能执行
[0:'xx',1:'yy']
@Dmitry人们似乎很难理解你的问题,但我认为这是一个很好的问题。不幸的是,除了你已经描述的选项之外,我没有任何其他建议。@Dmitry你已经考虑过的选项的一个缺点是,如果你不小心添加了,它们仍然容易受到复制/粘贴问题的影响有重复索引的东西,这些解决方案只会导致您丢失其中一个重复项。我只是想知道,除了注释每个条目外,是否有其他方法可以明确指定每个移动的id,这样,如果我忘记了,我就不必通过地图搜索来按名称查找id(这比从开始手动计算偏移要快)@Amit问题中的示例不是JSON,但从问题的标题来看,您可以预期稍后将使用这种格式。它不是JSON,但它是一个相关问题,以确保包含类似数据的JSON文件被正确索引,这有类似的问题,即使每个条目的索引不明显,并且容易出现错误索引。@我提到过d为什么这在原始帖子的讨论中不好。如果我决定更改一个项目的索引,而忘记更改内部索引,则会有一个问题,这意味着需要维护一个不变。你是对的,漏洞是一个严重的问题,使用贴图或将我的对象转换为数组可能比使用数组。我也没有证据表明访问对象比访问数组慢得多,因此,也许有理由将其作为一个对象来保存,以使插入更容易、更安全(以防出现漏洞,尽管这种数据是相当永久的,在不创建新表的情况下不打算删除)。如果有预期的删除,我会毫无疑问地使用对象。@Dmitry如果您真的只关心性能,并且保证不会出现漏洞,那么数组是最快的,因为访问元素的恒定开销仍然比访问映射的开销小。但是,插入或访问的计算复杂性数组和映射中的元素为常数O(1)-取决于映射的实现方式和一些通常不需要考虑的条件。@这就是我为什么要问的原因,因为没有漏洞,任何重新排序/重新设计都将是一个新的移动表。对象开销似乎过大,但javascript数组不是c数组,它们更多的是稀疏数组,因此它们应该能够f轻松处理漏洞,只要我显式设置索引,它们就可以处理,但正如我提到的,这在视觉上很烦人,可能比显式设置数组/拼接数组范围慢得多。这是一种不寻常的情况,几乎足以保证对象,但javascript数组应该能够处理它。好吧,你问过了对于O(1)解决方案,映射和数组都在O(1)中,只是常数不同。JS数组通常(现代JS引擎)由一个线性的易于寻址的存储支持,但前提是索引和索引中永远没有漏洞
let tmp = [
    {"0": {name: 'Astonish', type: 'Ghost'}},
    {"1": {name: 'Constrict', type: 'Normal'}},
    {"2": {name: 'Acid', type: 'Poison'}},
    {"3": {name: 'Ingrain', type: 'Grass'}}
];