I have a JavaScript object like this:
[{
name : "soccer",
elems : [
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
},
{
name : "basketball",
elems : [
{name : "Dallas Mavericks"}
]
}]
Now I want to search on this JavaScript object in the browser. The search for "FC" should give me something like this:
[
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
How to do this fast? Are there any JavaScript libs for this?
-
What is a JSON object? You mean you have a JSON string?Crescent Fresh– Crescent Fresh2009年11月30日 15:46:45 +00:00Commented Nov 30, 2009 at 15:46
-
He has a JavaScript object, of course. I'm assuming he said it's JSON because he asked a server for it as JSON or JSONP. :-)Nosredna– Nosredna2009年11月30日 15:48:37 +00:00Commented Nov 30, 2009 at 15:48
6 Answers 6
You might like using jLinq (personal project)
http://hugoware.net:4000/Projects/jLinq
Works like LINQ but for JSON and it allows you to extend it and modify it however you want to. There is already a bunch of prebuilt methods to check values and ranges.
Comments
Seeing as though the only helpful answers have been referencing third party libraries - here's your native javascript solution. For anyone that only wants a few lines of code rather than a stack:
The function:
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;
}
A native .map() function:
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;
}
Your object:
(skimmed from your posted abject):
myObject = {
name : "soccer",
elems : [
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
},
{
name : "basketball",
elems : [
{name : "Dallas Mavericks"}
]
}
For usage:
(This will search your myObject.elems array for a 'name' matching 'FC')
var matched = myObject.elems.findValue('name', 'FC');
console.log(matched);
The result - check your console:
[Object, Object, findValue: function]
0: Object
name: "FC Barcelona"
__proto__: Object
1: Object
name: "Liverpool FC"
__proto__: Object
length: 2
__proto__: Array[0]
Comments
Try jOrder. http://github.com/danstocker/jorder
It's optimized for fast O(logn) search and sorting on large (thousands of rows) tables in JS.
As opposed to array iteration, which most of the answers here are based on, jOrder uses indexes to filter data. Just to give you an idea, free-text search on a 1000-row table completes about 100 times faster than iteration. The bigger the table, the better ratio you get.
However jOrder can't process the format of your sample data. But if you re-format it like this:
var teams =
[
{ sport : "soccer", team: "FC Barcelona" },
{ sport : "soccer", team: "Liverpool FC" },
{ sport : "basketball", team : "Dallas Mavericks"}
]
You can get the desired results by first setting up a jOrder table:
var table = jOrder(teams)
.index('teams', ['team'], { grouped: true, ordered: true, type: jOrder.text });
And then running a search on it:
var hits = table.where([{ team: 'FC' }], { mode: jOrder.startof });
And you'll get exactly the two rows you needed. That's it.
Comments
The straightforward way to do this is simply to iterate over every property of the object and apply a test function to them (in this case, value.contains("FC")).
If you want it to go faster, you'd either need to implement some kind of caching (which could be eagerly populated in the background ahead of any queries), or perhaps precalculate the result of various popular test functions.
4 Comments
You could do this with regular expressions performed against a serialized JSON string:
var jsonString = "[{ name : \"soccer\", elems : [ {name : \"FC Barcelona\"}"
+", {name : \"Liverpool FC\"}]},{name : \"basketball\",elems : ["
+"{name : \"Dallas Mavericks\"} ]}]";
var pattern = /\s*([\w\d_]+)\s*:\s*((\"[^\"]*(your pattern here)[^\"]*\")|(\'[^\']*(your pattern here)[^\']*\'))\s*/g;
var foundItems = [];
var match;
while(match = pattern.exec(jsonString)){
foundItems.push(match[0]);
}
var foundJSON = "[{" + foundItems.join("}, {") + "}]";
var foundArray = eval(foundJSON);
I haven't tested the loop part of this, but the Regex seems to be working well for me with simple tests in firebug.
Comments
In regards to AngularJS, you can do this:
var item = "scope-ng-model";
(angular.element('form[name="myForm"]').scope())[item] = newVal;