为JavaScript创建高效的JSON映射
我们有一种情况,最好用类比来描述。让我们假设名称和city+state+zipcode之间有一个映射。这里的名称保证是唯一的。我们的样本数据(改编自)如下:为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
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"
}
}