在 JavaScript 中查找 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1946165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JSON find in JavaScript
提问by zapping
Is there a better way other than looping to find data in JSON? It's for edit and delete.
除了循环在JSON 中查找数据之外,还有更好的方法吗?它用于编辑和删除。
for(var k in objJsonResp) {
if (objJsonResp[k].txtId == id) {
if (action == 'delete') {
objJsonResp.splice(k,1);
} else {
objJsonResp[k] = newVal;
}
break;
}
}
The data is arranged as list of maps. Like:
数据按地图列表排列。喜欢:
[
{id:value, pId:value, cId:value,...},
{id:value, pId:value, cId:value,...},
...
]
回答by T.J. Crowder
(You're not searching through "JSON", you're searching through an array -- the JSON string has already been deserialized into an object graph, in this case an array.)
(您不是搜索“JSON”,而是搜索数组——JSON 字符串已经反序列化为对象图,在本例中为数组。)
Some options:
一些选项:
Use an Object Instead of an Array
使用对象而不是数组
If you're in control of the generation of this thing, does it haveto be an array? Because if not, there's a much simpler way.
如果你控制了这个东西的生成,它一定是一个数组吗?因为如果没有,有一个更简单的方法。
Say this is your original data:
假设这是您的原始数据:
[
{"id": "one", "pId": "foo1", "cId": "bar1"},
{"id": "two", "pId": "foo2", "cId": "bar2"},
{"id": "three", "pId": "foo3", "cId": "bar3"}
]
Could you do the following instead?
您可以改为执行以下操作吗?
{
"one": {"pId": "foo1", "cId": "bar1"},
"two": {"pId": "foo2", "cId": "bar2"},
"three": {"pId": "foo3", "cId": "bar3"}
}
Then finding the relevant entry by ID is trivial:
然后通过 ID 查找相关条目是微不足道的:
id = "one"; // Or whatever
var entry = objJsonResp[id];
...as is updating it:
...正在更新它:
objJsonResp[id] = /* New value */;
...and removing it:
...并删除它:
delete objJsonResp[id];
This takes advantage of the fact that in JavaScript, you can index into an object using a property name as a string -- and that string can be a literal, or it can come from a variable as with idabove.
这利用了这样一个事实,即在 JavaScript 中,您可以使用属性名称作为字符串索引到对象中——并且该字符串可以是文字,也可以来自上述变量id。
Putting in an ID-to-Index Map
放入 ID 到索引映射
(Dumb idea, predates the above. Kept for historical reasons.)
(愚蠢的想法,早于上述。由于历史原因而保留。)
It looks like you need this to be an array, in which case there isn't really a better way than searching through the array unless you want to put a map on it, which you could do if you have control of the generation of the object. E.g., say you have this originally:
看起来您需要将其作为数组,在这种情况下,没有比搜索数组更好的方法,除非您想在其上放置地图,如果您可以控制数组的生成,则可以这样做目的。例如,假设你最初有这个:
[
{"id": "one", "pId": "foo1", "cId": "bar1"},
{"id": "two", "pId": "foo2", "cId": "bar2"},
{"id": "three", "pId": "foo3", "cId": "bar3"}
]
The generating code could provide an id-to-index map:
生成代码可以提供一个 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"}
]
}
Then getting an entry for the id in the variable idis trivial:
然后在变量中获取 id 的条目id是微不足道的:
var index = objJsonResp.index[id];
var obj = objJsonResp.data[index];
This takes advantage of the fact you can index into objects using property names.
这利用了您可以使用属性名称索引对象的事实。
Of course, if you do that, you have to update the map when you modify the array, which could become a maintenance problem.
当然,如果这样做,则在修改数组时必须更新映射,这可能会成为维护问题。
But if you're not in control of the generation of the object, or updating the map of ids-to-indexes is too much code and/ora maintenance issue, then you'll have to do a brute force search.
但是,如果您无法控制对象的生成,或者更新 ids-to-indexes 的映射是代码过多和/或维护问题,那么您将不得不进行蛮力搜索。
Brute Force Search (corrected)
蛮力搜索(更正)
Somewhat OT (although you didask if there was a better way :-) ), but your code for looping through an array is incorrect. Details here, but you can't use for..into loop through array indexes (or rather, if you do, you have to take special pains to do so); for..inloops through the properties of an object, not the indexes of an array. Your best bet with a non-sparse array (and yours is non-sparse) is a standard old-fashioned loop:
有点过时(尽管您确实问过是否有更好的方法 :-) ),但是您循环遍历数组的代码不正确。此处有详细信息,但您不能使用for..in循环遍历数组索引(或者更确切地说,如果这样做,您必须特别注意这样做);for..in循环遍历对象的属性,而不是数组的索引。使用非稀疏数组(而你的数组是非稀疏数组)的最佳选择是标准的老式循环:
var k;
for (k = 0; k < someArray.length; ++k) { /* ... */ }
or
或者
var k;
for (k = someArray.length - 1; k >= 0; --k) { /* ... */ }
Whichever you prefer (the latter is not always faster in all implementations, which is counter-intuitive to me, but there we are). (With a sparsearray, you might use for..inbut again taking special pains to avoid pitfalls; more in the article linked above.)
无论你喜欢哪个(后者在所有实现中并不总是更快,这对我来说是违反直觉的,但我们就是这样)。(对于稀疏数组,您可能会for..in再次使用,但要特别注意避免陷阱;更多内容请参见上面链接的文章。)
Using for..inon an array seemsto work in simple cases because arrays have properties for each of their indexes, and their only other default properties (lengthand their methods) are marked as non-enumerable. But it breaks as soon as you set (or a framework sets) any other properties on the array object (which is perfectly valid; arrays are just objects with a bit of special handling around the lengthproperty).
使用for..in阵列上似乎在简单的情况下工作,因为阵列具有属性他们的每一个指标,而他们唯一的默认属性(length和它们的方法)被标记为不可枚举。但是一旦您在数组对象上设置(或框架设置)任何其他属性(这是完全有效的;数组只是对length属性进行了一些特殊处理的对象),它就会中断。
回答by Travis J
I had come across this issue for a complex model with several nested objects. A good example of what I was looking at doing would be this: Lets say you have a polaroid of yourself. And that picture is then put into a trunk of a car. The car is inside of a large crate. The crate is in the hold of a large ship with many other crates. I had to search the hold, look in the crates, check the trunk, and then look for an existing picture of me.
我遇到了一个具有多个嵌套对象的复杂模型的问题。我正在考虑做的一个很好的例子是:假设你有一个自己的宝丽来。然后将那张照片放入汽车后备箱。汽车在一个大板条箱内。板条箱与许多其他板条箱放在一艘大船的货舱中。我不得不搜索货舱,查看板条箱,检查行李箱,然后寻找我现有的照片。
I could not find any good solutions online to use, and using .filter()only works on arrays. Most solutions suggested just checking to see if model["yourpicture"]existed. This was very undesirable because, from the example, that would only search the hold of the ship and I needed a way to get them from farther down the rabbit hole.
我在网上找不到任何好的解决方案来使用,并且.filter()只适用于阵列。大多数解决方案建议只检查是否model["yourpicture"]存在。这是非常不可取的,因为从这个例子来看,这只会搜索船的货舱,我需要一种方法将它们从更远的兔子洞中取出。
This is the recursive solution I made. In comments, I confirmed from T.J. Crowder that a recursive version would be required. I thought I would share it in case anyone came across a similar complex situation.
这是我做的递归解决方案。在评论中,我从 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;
}
This will start from a given object inside of the graph, and recurse down any objects found. I use it like this:
这将从图中的给定对象开始,并向下递归找到任何对象。我像这样使用它:
var liveData = [];
for( var items in viewmodel.Crates )
{
if( ContainsKeyValue( viewmodel.Crates[items], "PictureId", 6 ) === true )
{
liveData.push( viewmodel.Crates[items] );
}
}
Which will produce an array of the Crates which contained my picture.
这将产生一个包含我的图片的 Crates 数组。
回答by Hakan Bilgin
Zapping - you can use this javascript lib; DefiantJS. There is no need to restructure JSON data into objects to ease searching. Instead, you can search the JSON structure with an XPath expression like this:
Zapping - 你可以使用这个 javascript 库;DefiantJS。无需将 JSON 数据重组为对象以简化搜索。相反,您可以使用 XPath 表达式搜索 JSON 结构,如下所示:
var data = [
{
"id": "one",
"pId": "foo1",
"cId": "bar1"
},
{
"id": "two",
"pId": "foo2",
"cId": "bar2"
},
{
"id": "three",
"pId": "foo3",
"cId": "bar3"
}
],
res = JSON.search( data, '//*[id="one"]' );
console.log( res[0].cId );
// 'bar1'
DefiantJS extends the global object JSON with a new method; "search" which returns array with the matches (empty array if none were found). You can try it out yourself by pasting your JSON data and testing different XPath queries here:
DefiantJS 使用新方法扩展了全局对象 JSON;“搜索”返回带有匹配项的数组(如果没有找到则为空数组)。您可以通过粘贴 JSON 数据并在此处测试不同的 XPath 查询来自己尝试:
http://www.defiantjs.com/#xpath_evaluator
http://www.defiantjs.com/#xpath_evaluator
XPath is, as you know, a standardised query language.
如您所知,XPath 是一种标准化的查询语言。
回答by Rob Evans
If you are doing this in more than one place in your application it would make sense to use a client-side JSON database because creating custom search functions is messy and less maintainable than the alternative.
如果您在应用程序中的多个位置执行此操作,则使用客户端 JSON 数据库是有意义的,因为创建自定义搜索函数比另一种方法更麻烦且不易维护。
Check out ForerunnerDB which provides you with a very powerful client-side JSON database system and includes a very simple query language to help you do exactly what you are looking for:
查看 ForerunnerDB,它为您提供了一个非常强大的客户端 JSON 数据库系统,并包含一个非常简单的查询语言来帮助您准确地执行您正在寻找的操作:
// Create a new instance of ForerunnerDB and then ask for a database
var fdb = new ForerunnerDB(),
db = fdb.db('myTestDatabase'),
coll;
// Create our new collection (like a MySQL table) and change the default
// primary key from "_id" to "id"
coll = db.collection('myCollection', {primaryKey: 'id'});
// Insert our records into the collection
coll.insert([
{"name":"my Name","id":12,"type":"car owner"},
{"name":"my Name2","id":13,"type":"car owner2"},
{"name":"my Name4","id":14,"type":"car owner3"},
{"name":"my Name4","id":15,"type":"car owner5"}
]);
// Search the collection for the string "my nam" as a case insensitive
// regular expression - this search will match all records because every
// name field has the text "my Nam" in it
var searchResultArray = coll.find({
name: /my nam/i
});
console.log(searchResultArray);
/* Outputs
[
{"name":"my Name","id":12,"type":"car owner"},
{"name":"my Name2","id":13,"type":"car owner2"},
{"name":"my Name4","id":14,"type":"car owner3"},
{"name":"my Name4","id":15,"type":"car owner5"}
]
*/
Disclaimer: I am the developer of ForerunnerDB.
免责声明:我是 ForerunnerDB 的开发者。
回答by Justin Swartsel
If the JSON data in your array is sorted in some way, there are a variety of searches you could implement. However, if you're not dealing with a lot of data then you're probably going to be fine with an O(n) operation here (as you have). Anything else would probably be overkill.
如果您的数组中的 JSON 数据以某种方式排序,则您可以实施多种搜索。但是,如果您没有处理大量数据,那么您可能会在这里进行 O(n) 操作(就像您一样)。其他任何事情都可能是矫枉过正。

