Javascript中键/值对的对象与数组

Javascript中键/值对的对象与数组,javascript,data-structures,Javascript,Data Structures,假设您有一个非常简单的数据结构: (personId, name) …您希望在javascript变量中存储其中的一些。在我看来,你有三个选择: // a single object var people = { 1 : 'Joe', 3 : 'Sam', 8 : 'Eve' }; // or, an array of objects var people = [ { id: 1, name: 'Joe'}, { id: 3, name: 'Sam'}

假设您有一个非常简单的数据结构:

(personId, name)
…您希望在javascript变量中存储其中的一些。在我看来,你有三个选择:

// a single object
var people = {
    1 : 'Joe',
    3 : 'Sam',
    8 : 'Eve'
};

// or, an array of objects
var people = [
    { id: 1, name: 'Joe'},
    { id: 3, name: 'Sam'},
    { id: 8, name: 'Eve'}
];

// or, a combination of the two
var people = {
    1 : { id: 1, name: 'Joe'},
    3 : { id: 3, name: 'Sam'},
    8 : { id: 8, name: 'Eve'}
};
第二个或第三个选项显然是一种方法,如果您有(或期望您可能有)多个“值”部分要存储(例如,添加它们的年龄或其他内容),那么,为了论证起见,让我们假设此结构中永远不会需要更多的数据值。你选择哪一个?为什么



编辑:该示例现在显示了最常见的情况:非顺序ID。

实际上,还有第四个选项:

var people = ['Joe', 'Sam', 'Eve'];
因为你的值是连续的。(当然,您必须加/减一——或者将undefined作为第一个元素)

就个人而言,我会选择你的(1)或(3),因为这将是通过ID查找某人的最快方法(最坏情况下是O logn)。如果您必须在(2)中找到id 3,您可以通过索引查找它(在这种情况下,my(4)是可以的),或者您必须搜索-O(n)

澄清:我说O(logn)是最糟糕的,因为AFAIK和实现可能决定使用平衡树而不是哈希表。假设冲突最小,哈希表将是O(1)

编辑自nickf:我已经改变了OP中的例子,所以这个答案可能不再有意义了。抱歉

后期编辑 好的,编辑后,我选择选项(3)。它是可扩展的(易于添加新属性),具有快速查找功能,并且可以进行迭代。如果需要,它还允许您从条目返回到ID

如果(a)您需要节省内存,选项(1)将非常有用;(b) 您永远不需要从对象返回到id;(c) 您永远不会扩展存储的数据(例如,您不能添加此人的姓氏)


如果您(a)需要保留订单,则选项(2)是好的;(b) 需要迭代所有元素;(c) 不需要按id查找元素,除非它是按id排序的(您可以在O(logn)中进行二进制搜索)。当然,请注意,如果您需要对其进行排序,那么您将在插入时支付费用。

每个解决方案都有其使用案例

我认为,如果您试图定义一对一的关系(例如简单的映射),特别是如果您需要将该键用作查找键,那么第一种解决方案是很好的

一般来说,第二种解决方案对我来说是最健壮的,如果我不需要快速查找键,我可能会使用它:

  • 这是自我描述,所以你不需要 必须依靠任何人使用 让人们知道密钥是用户的id
  • 每个对象都是独立的, 哪个更适合传递数据 其他地方-而不是两个参数 (身份证和姓名)你只是随便走走 人们
  • 这是一个罕见的问题,但有时 键值可能对无效 用作键。例如,我曾经 想要映射字符串转换 (如“:”至“>”),但自“:” 不是我必须使用的有效变量名 使用第二种方法
  • 它很容易扩展,以防万一 沿着这条线的某个地方你需要 向某些(或所有)用户添加更多数据。 (对不起,我知道你的 但这是一个 重要方面。)

如果您需要快速查找时间+上面列出的一些优点(传递数据,自我描述),那么第三种方法会很好。但是,如果您不需要快速查找时间,则会非常麻烦。此外,无论哪种方式,如果对象中的id与人中的id有所不同,您都会有出错的风险。

假设数据永远不会更改,第一个(单个对象)选项是最好的


结构的简单性意味着它是解析的最快方法,在小的情况下,很少(或从不)解析更改像这样的数据集,我只能想象它会被频繁执行-在这种情况下,开销最小是最好的选择。

鉴于您的限制,您将永远只使用名称作为值,我会选择第一个选项。它最干净,开销最小,查找速度最快。

第三个选项是最适合任何前瞻性应用程序。您可能希望在个人记录中添加更多字段,因此第一个选项不合适。此外,您很可能需要存储大量的个人,并且希望快速查找记录,从而将其转储到一个简单的数组中(如选项2所示)这也不是个好主意

第三种模式让您可以选择使用任何字符串作为ID,具有复杂的Person结构,并在固定时间内获取和设置Person记录。这绝对是一种方法


选项3缺少的一点是稳定的确定性排序(这是选项2的优势)。如果您需要此功能,我建议您在需要按顺序列出人员时,保留一个有序的人员ID数组作为一个单独的结构。优点是您可以为同一数据集的不同顺序保留多个这样的数组。

我创建了一个小库来管理键值对

它使用

  • 用于存储键的对象,允许快速删除和值检索 运作及
  • 允许真正快速的值迭代的链表

希望有帮助:)

我理解为什么(1)和(3)比(2)快,但我想知道你当时是如何得到O(log(n))的?它不应该是O(1),因为ID应该存储在哈希表中吗?我将logn设为最差,因为我可以看到一个实现决定使用平衡树而不是哈希表。当然,哈希表应该是O(1)[假设冲突最小],ID并不总是那么简单,它们很少是顺序IRL,这就是为什么需要指定它们。我承认这是一个糟糕的/模棱两可的例子。+1,您的答案并不比公认的答案差……但您的第四个解决方案并没有存储所有数据,因此这里有正确的第四个选项:
var people=[];人[