2009-11-30 96 views
12

我有一个JavaScript对象是这样的:搜索JavaScript对象

[{ 
    name : "soccer", 
    elems : [ 
     {name : "FC Barcelona"}, 
     {name : "Liverpool FC"} 
    ] 
}, 
{ 
    name : "basketball", 
    elems : [ 
     {name : "Dallas Mavericks"} 
    ] 
}] 

现在我想在浏览器这个JavaScript对象上进行搜索。为“FC”搜索应该给我这样的事情:

[ 
    {name : "FC Barcelona"}, 
    {name : "Liverpool FC"} 
] 

如何做到这一点快?有没有JavaScript的库?

+0

什么是一个JSON对象?你的意思是你有一个JSON *字符串*? – 2009-11-30 15:46:45

+0

他有一个JavaScript对象,当然。我假设他说这是JSON,因为他要求服务器将其作为JSON或JSONP。 :-) – Nosredna 2009-11-30 15:48:37

回答

7

虽然可以在直接的JavaScript做到这一点,underscore.js是一个很好的库来处理这些东西。你可以用“pluck”和“each”来实现它。

约underscore.js好处是,它存在时使用浏览器的内置电话。

+1

你也可以显示代码吗? – JerryGoyal 2015-12-19 10:11:38

+0

链接中断 – crh225 2016-08-31 21:19:39

+0

链接已修复。 – 2017-09-21 23:28:35

0

这样做的直接方法是简单地遍历对象的每个属性并将测试函数应用于它们(在本例中为value.contains("FC"))。如果你想让它变得更快,你可能需要实现某种缓存(可以在任何查询之前在后台急于填充),或者可能预先计算各种常用测试函数的结果。

+0

我想走得比O(n)快。我想过像http://en.wikipedia.org/wiki/Trie这样的东西,但如果没有必要,我不想亲自写这个。 – 2009-11-30 15:56:47

+0

@Juri,你是否愿意将对象预处理成不同的结构,或者你想使用该对象吗?当然,从一个结构转换到另一个结构是有成本的。如果你要对相同的数据进行大量搜索,这可能是值得的。 – Nosredna 2009-11-30 16:01:54

+0

@Nosredna:是的,预处理是绝对有可能的。 – 2009-11-30 16:19:27

12

你可能会喜欢使用JLINQ(个人项目)

http://Hugoware.net/Projects/jLinq

作品像LINQ但对于JSON,它可以扩展它,但是要修改它。已经有一些预先构建的方法来检查值和范围。

+0

这是一个伟大的项目。 – Nosredna 2009-11-30 20:18:45

+0

这是一个很棒的项目,也是一个漂亮的网页。我确实看到了一种你可能想纠正的类型...“阅读文档” – Nosredna 2009-11-30 20:21:35

+0

@Nosredna - 谢谢,我会检查它! – Hugoware 2009-11-30 20:37:31

0

您可以用对一个序列化JSON字符串进行正则表达式做到这一点:

​​

我没有测试过这种循环的一部分,但正则表达式似乎在简单测试是工作很适合我萤火虫。

+0

大声笑,谢谢你的修复,Crescent :) – JasonWyatt 2009-11-30 17:47:03

+1

...所以现在OP有两个问题... – vtortola 2014-06-09 23:32:41

3

尝试jOrder。 http://github.com/danstocker/jorder

它针对JS中大型(数千行)表上的快速O(logn)搜索和排序进行了优化。

与数组迭代相比,这里的大多数答案都基于jOrder使用索引来过滤数据。为了给您一个想法,1000行表格上的自由文本搜索完成速度比迭代快100倍。桌子越大,你得到的比例越好。

然而jOrder无法处理您的样本数据的格式。但是,如果你重新格式化这样的:

var teams = 
[ 
{ sport : "soccer", team: "FC Barcelona" }, 
{ sport : "soccer", team: "Liverpool FC" }, 
{ sport : "basketball", team : "Dallas Mavericks"} 
] 

您可以先建立一个jOrder表得到想要的结果:

var table = jOrder(teams) 
    .index('teams', ['team'], { grouped: true, ordered: true, type: jOrder.text }); 

然后在其上运行一个搜索:

var hits = table.where([{ team: 'FC' }], { mode: jOrder.startof }); 

你会得到你需要的两行。而已。

-2

在问候AngularJS,你可以这样做:

var item = "scope-ng-model"; 

(angular.element('form[name="myForm"]').scope())[item] = newVal; 
+0

这只设置AngularJS Scope对象的属性,它不搜索任何东西。 – 2014-05-30 18:57:58

+0

这并没有解决操作问题。 – captainrad 2016-11-14 20:53:59

5

看到好像是唯一有用的答案已经被引用的第三方库 - 这里是你的本地JavaScript的解决方案。对于任何人,只希望的几行代码,而不是堆栈:

功能:

Array.prototype.findValue = function(name, value){ 
    var array = map(this, function(v,i){ 
     var haystack = v[name]; 
     var needle = new RegExp(value); 
     // check for string in haystack 
     // return the matched item if true, or null otherwise 
     return needle.test(haystack) ? v : null; 
    }); 
    return array; 
} 

土生土长.map()功能:

map = function(array, mapFunction) { 
     var newArray = new Array(array.length); 
     for(var i = 0; i < array.length; i++) { 
     newArray[i] = mapFunction(array[i]); 
     } 
     return newArray; 
} 

你的对象:

(脱脂从您发布的目标):

myObject = { 
     name : "soccer", 
     elems : [ 
      {name : "FC Barcelona"}, 
      {name : "Liverpool FC"} 
     ] 
    }, 
    { 
     name : "basketball", 
     elems : [ 
      {name : "Dallas Mavericks"} 
     ] 
    } 

有关使用方法:

(这将搜索您myObject.elems阵列的 '名字' 匹配 'FC')

var matched = myObject.elems.findValue('name', 'FC'); 
console.log(matched); 

结果 - 检查你的控制台:

[Object, Object, findValue: function] 
0: Object 
name: "FC Barcelona" 
__proto__: Object 
1: Object 
name: "Liverpool FC" 
__proto__: Object 
length: 2 
__proto__: Array[0]