为JavaScript创建高效的JSON映射

为JavaScript创建高效的JSON映射,javascript,json,Javascript,Json,我们有一种情况,最好用类比来描述。让我们假设名称和city+state+zipcode之间有一个映射。这里的名称保证是唯一的。我们的样本数据(改编自)如下: James Butt: New Orleans LA 70116 Josephine Darakjy: Brighton MI 48116 Art Venere: Bridgeport NJ 8014 Lenna Paprocki: Anchorage AK 99501 Donette Foller: Hamilton OH 45011 S

我们有一种情况,最好用类比来描述。让我们假设名称和city+state+zipcode之间有一个映射。这里的名称保证是唯一的。我们的样本数据(改编自)如下:

James Butt: New Orleans LA 70116
Josephine Darakjy: Brighton MI 48116
Art Venere: Bridgeport NJ 8014
Lenna Paprocki: Anchorage AK 99501
Donette Foller: Hamilton OH 45011
Simona Morasca: Ashland OH 44805
Mitsue Tollner: Chicago IL 60632
Leota Dilliard: San Jose CA 95111
Sage Wieser: Sioux Falls SD 57105
Kris Marrier: Baltimore MD 21224
在这种情况下,什么是好的JSON结构?从处理的角度来看,我们正在寻找更高效的JavaScript。我们至少看到两种选择

选项1

{
"James Butt":  "New Orleans LA 70116",
"Josephine Darakjy":  "Brighton MI 48116",
"Art Venere":  "Bridgeport NJ 8014",
"Lenna Paprocki":  "Anchorage AK 99501",
"Donette Foller":  "Hamilton OH 45011",
"Simona Morasca":  "Ashland OH 44805",
"Mitsue Tollner":  "Chicago IL 60632",
"Leota Dilliard":  "San Jose CA 95111",
"Sage Wieser":  "Sioux Falls SD 57105",
"Kris Marrier":  "Baltimore MD 21224"
}
选项2

[
   {
      "name": "James Butt",
      "address": "New Orleans LA 70116"
   },
   {
      "name": "Josephine Darakjy",
      "address": "Brighton MI 48116"
   },
   {
      "name": "Art Venere",
      "address": "Bridgeport NJ 8014"
   },
   {
      "name": "Lenna Paprocki",
      "address": "Anchorage AK 99501"
   },
   {
      "name": "Donette Foller",
      "address": "Hamilton OH 45011"
   },
   {
      "name": "Simona Morasca",
      "address": "Ashland OH 44805"
   },
   {
      "name": "Mitsue Tollner",
      "address": "Chicago IL 60632"
   },
   {
      "name": "Leota Dilliard",
      "address": "San Jose CA 95111"
   },
   {
      "name": "Sage Wieser",
      "address": "Sioux Falls SD 57105"
   },
   {
      "name": "Kris Marrier",
      "address": "Baltimore MD 21224"
   }
]
  
备选案文1: 这是一个坏主意,即使你完全确定没有重复的名字。首先,现实世界中不存在没有重复名称的情况。第二,如果名称包含特殊字符怎么办

备选案文2: 这是格式化数据的正确方法,除非注释中指出,否则每个名称还应映射一个唯一的ID字段


const data = [
   {
      "id": 1, 
      "name": "James Butt",
      "address": "New Orleans LA 70116"
   }, 
   ...
];

user = data.filter(({id})=>id==1); //gives you this user
user = data.filter(({name})=>name=='James Butt'); //also works
在数据构造中添加唯一ID的原因是避免依赖于这些ID插入
数据
数组的顺序。来自真实世界数据库的任何数据都将始终具有某种唯一的ID字段,可以是数字或字母数字。但是,返回数据的顺序将不能可靠地指示用户的真实id。

说到效率(以及防止重复的名称-键冲突)
我会将字符串数据映射到一个对象中,其中键是唯一ID(就像在数据库中一样):

提取单个记录: 我们通过立即提取给定键ID的记录来提高速度,就像查找内存地址一样,而不是总是迭代(在最坏的情况下是整个)数组来搜索单个记录

提取多个记录: 您总是可以使用
Object.keys()
Object.values()
Object.entries()
-和循环来迭代对象,就像使用数组一样

由于ES2015对象键的顺序是可预测的,您可以毫不费力地按ID对对象进行开箱排序-默认情况下,记录是按创建日期组织的-因为DB行ID是增量的

示例:按ID或值获取记录
const用户={
6 : {
“id”:6,
“姓名”:“Antonette Darakjy”,
“地址”:“密歇根州布莱顿48116”
},
7 : {
“id”:7,
“姓名”:“詹姆斯·巴特”,
“地址”:“新奥尔良洛杉矶70116”
},
19 : {
“id”:19,
“姓名”:“约瑟芬·达拉基”,
“地址”:“密歇根州布莱顿48116”
},
};
//通过身份证
console.log(用户[7]);//无需迭代数万条记录
//按键值获取
//返回筛选用户的数组
const filterBy=(prop,val)=>Object.values(用户).filter(用户=>{
返回用户[prop]==val;
});

控制台日志(filterBy(“地址”,“布莱顿MI 48116”)不确定你所说的“处理效率”到底是什么意思,但猜测你希望通过姓名高效地查找人们的地址。建议的解决方案需要迭代整个集合,因此它们可以处理500条记录,而不会处理1M条记录

另外,正如其他人所提到的,名称冲突是真实存在的(特别是当您获得1百万条记录集时),因此假设您需要数据结构中的两个功能:

  • 按名称进行有效地址查找
  • 没有名字冲突
  • 这意味着您需要一个键,其中键是人名,值是地址集。基本上,第一个选项是将地址数组作为字段值。或者,您可以使用更高效的添加/删除和更方便地访问存储的记录数(唯一人名)


    使用数组时,在V8实现中映射(和设置)O(1)
    时间复杂度与
    线性
    时间。因此它们是高效的。

    两者都可以轻松地来回转换。关于访问数据,第一种方法可以利用迭代,因为您可以直接通过其键属性(名称)访问唯一记录。我宁愿使用和ID,而不是名称作为键。我选择两个。该结构将重新编译您可以从db查询中获得的内容。正如@RokoC.Buljan所说,添加一个唯一的ID是最好的选择,除了将ID存储在数据中之外,还可以将ID用作对象密钥,这对于提高效率来说是一个很好的答案,只要您知道密钥是唯一的并且正确转义。在许多情况下,我们保留一个普通数组和一个链接到相同数组元素的对象,这些数组元素由ID设置关键字。特别是因为如果我们想按ID搜索,哈希键搜索非常快,但是如果你想过滤或循环它们,在数组上这样做会更快(并且不需要编写自己的map/filter/reduce代码)@joshstrike如果你想循环,过滤一个数组,是的,你确实需要编写一些代码,是的,使用
    filter()
    reduce()
    或任何其他Array.prototype方法-在V8引擎中的速度与使用
    for
    @RokoC.Buljan一样快。我的观点只是使用.filter()在数组中使用Object.values(n).reduce()比在其中使用哈希查找更快。这就是为什么要保留模型的两个副本,一个在平面数组中,另一个在对象中保留一组id引用。RokoCBuljan,JSBench引用?无论在JS中实现得有多好,在一定规模上,为循环(在齐次数据上)建立索引的整数几乎总是比reduce(在V8上)快一个数量级,尽管这被夸大了,因为它可能是您的瓶颈,因为速度是如此之小@x1n13y84issmd42是引用的一个浅拷贝,可以立即进行GCD(并且大部分是优化的),因此内存的整个翻倍被夸大了,即使有些真实。我不能说我不同意reduce的观点,尽管这在很大程度上取决于意见。@x1n13y84issmd42绝对同意<代码>.reduce是ind
    {
       7 : {
          "id": 7,
          "name": "James Butt",
          "address": "New Orleans LA 70116"
       },
       19 : {
          "id": 19,
          "name": "Josephine Darakjy",
          "address": "Brighton MI 48116"
       }
    }