3 回答

TA贡献1871条经验 获得超13个赞
(您不是在搜索“JSON”,而是在搜索数组 - JSON字符串已经被反序列化为对象图,在本例中是一个数组。)
一些选择:
使用对象而不是数组
如果你控制了这个东西的产生,它必须是一个数组吗?因为如果没有,那就有一个更简单的方法。
说这是你的原始数据:
[ {"id": "one", "pId": "foo1", "cId": "bar1"}, {"id": "two", "pId": "foo2", "cId": "bar2"}, {"id": "three", "pId": "foo3", "cId": "bar3"}]
你可以做以下事吗?
{ "one": {"pId": "foo1", "cId": "bar1"}, "two": {"pId": "foo2", "cId": "bar2"}, "three": {"pId": "foo3", "cId": "bar3"}}
然后通过ID查找相关条目是微不足道的:
id = "one"; // Or whatevervar entry = objJsonResp[id];
......正如更新它:
objJsonResp[id] = /* New value */;
...并删除它:
delete objJsonResp[id];
这利用了以下事实:在JavaScript中,您可以使用属性名称作为字符串索引到对象 - 并且该字符串可以是文字,或者它可以来自变量,id
如上所述。
放入ID到索引图
(愚蠢的想法,早于上述。保留历史原因。)
看起来你需要将它作为一个数组,在这种情况下除了你想在它上面放置一个地图之外没有比搜索数组更好的方法,如果你能控制它的生成就可以做到这一点。宾语。比如说,你最初有这个:
[ {"id": "one", "pId": "foo1", "cId": "bar1"}, {"id": "two", "pId": "foo2", "cId": "bar2"}, {"id": "three", "pId": "foo3", "cId": "bar3"}]
生成代码可以提供id-to-index映射:
{ "index": { "one": 0, "two": 1, "three": 2 }, "data": [ {"id": "one", "pId": "foo1", "cId": "bar1"}, {"id": "two", "pId": "foo2", "cId": "bar2"}, {"id": "three", "pId": "foo3", "cId": "bar3"} ]}
然后在变量中获取id的条目id
是微不足道的:
var index = objJsonResp.index[id];var obj = objJsonResp.data[index];
这利用了您可以使用属性名称索引到对象的事实。
当然,如果这样做,则必须在修改阵列时更新映射,这可能会成为维护问题。
但是,如果您无法控制对象的生成,或者更新ids-to-index的映射是太多的代码和/或维护问题,那么您将不得不进行暴力搜索。
蛮力搜索(更正)
有点OT(虽然你确实问过是否有更好的方法:-)),但循环数组的代码是不正确的。这里有详细介绍,但你不能for..in
用来遍历数组索引(或者更确切地说,如果你这样做,你必须特别努力); for..in
循环遍历对象的属性,而不是数组的索引。使用非稀疏数组(和你的非稀疏数组)最好的选择是标准的老式循环:
var k;for (k = 0; k < someArray.length; ++k) { /* ... */ }
要么
var k;for (k = someArray.length - 1; k >= 0; --k) { /* ... */ }
无论你喜欢什么(后者在所有实现中并不总是更快,这对我来说是违反直觉的,但我们确实如此)。(使用稀疏数组,您可以使用for..in
但是再次采取特殊的措施来避免陷阱;在上面链接的文章中更多。)
使用for..in
阵列上似乎在简单的情况下工作,因为数组为每个它们的索引,而他们唯一的默认属性(属性length
和它们的方法)被标记为不可枚举。但是一旦你设置(或框架设置)数组对象上的任何其他属性(它完全有效;数组只是在length
属性周围进行一些特殊处理的对象),它就会中断。

TA贡献1712条经验 获得超3个赞
我遇到过这个问题的复杂模型有几个嵌套对象。我正在做的事情的一个很好的例子是:让我们说你有自己的宝丽来。然后将那张照片放入汽车后备箱。汽车在一个大箱子里面。箱子里装着一艘装有许多其他板条箱的大船。我不得不搜索一下,看看板条箱,检查后备箱,然后寻找我现有的照片。
我找不到任何在线使用的好解决方案,并且.filter()
只能在阵列上使用。大多数解决方案建议只检查是否model["yourpicture"]
存在。这是非常不受欢迎的,因为从这个例子来说,只能搜索船的舱位,我需要一种方法让它们从兔子洞的下方越来越远。
这是我提出的递归解决方案。在评论中,我从TJ Crowder确认需要一个递归版本。我想我会分享它,以防任何人遇到类似的复杂情况。
function ContainsKeyValue( obj, key, value ){ if( obj[key] === value ) return true; for( all in obj ) { if( obj[all] != null && obj[all][key] === value ){ return true; } if( typeof obj[all] == "object" && obj[all]!= null ){ var found = ContainsKeyValue( obj[all], key, value ); if( found == true ) return true; } } return false;}
这将从图形内的给定对象开始,然后递归找到的任何对象。我这样使用它:
var liveData = [];for( var items in viewmodel.Crates ){ if( ContainsKeyValue( viewmodel.Crates[items], "PictureId", 6 ) === true ) { liveData.push( viewmodel.Crates[items] ); }}
这会产生一个包含我的照片的Crates数组。
添加回答
举报