I'm using PHP to fetch "tasks" from my database and encoding it as JSON. When I transfer the data over to javascript, I end up with something like this:
Array {
[0] => Task {
id: 2,
name: 'Random Task',
pleted: 0
}
[1] => Task {
id: 8,
name: 'Another task',
pleted: 1
}
}
etc.
I guess my real question is, what's the most efficient way to find the task by its id? Iterating through the array and checking each object seems like it might not be the most efficient? Is there any other way to do this?
I'm using PHP to fetch "tasks" from my database and encoding it as JSON. When I transfer the data over to javascript, I end up with something like this:
Array {
[0] => Task {
id: 2,
name: 'Random Task',
pleted: 0
}
[1] => Task {
id: 8,
name: 'Another task',
pleted: 1
}
}
etc.
I guess my real question is, what's the most efficient way to find the task by its id? Iterating through the array and checking each object seems like it might not be the most efficient? Is there any other way to do this?
Share Improve this question edited Jun 25, 2010 at 6:34 Rodrick Chapman 5,5532 gold badges32 silver badges34 bronze badges asked Jun 25, 2010 at 6:31 RobRob 1,8851 gold badge14 silver badges26 bronze badges 3- Can you post the exact JSON response? – Rodrick Chapman Commented Jun 25, 2010 at 6:34
- 3 If you're always accessing by id, that should be the key. – Matthew Flaschen Commented Jun 25, 2010 at 6:35
- I may also be accessing by pleted, or folder (I only included the most basic example) – Rob Commented Jun 25, 2010 at 6:36
6 Answers
Reset to default 6The thing about Javascript objects is that they are essential maps. You can access properties through using both dot notation ("object.property") and also index notation ("object["property"]). You can also enumerate through its properties, either using a for (i...) or for (in...)
for (var i = 0; i < arrayObj.length; i++) { ... }
for (var prop in arrayObj) { ... }
What I have been doing recently is building some Linq-esque extensions to the array object:
Array.prototype.Where = function(predicate) {
Throw.IfArgumentNull(predicate, "predicate");
Throw.IfNotAFunction(predicate, "predicate");
var results = new Array();
for (var i = 0; i < this.length; i++) {
var item = this[i];
if (predicate(item))
results.push(item);
}
return results;
};
Ignoring my custom Throw type, it basically allows you do to something like:
var item = arrayObj.Where(function(i) { return (i.id == 8); }).FirstOrDefault();
I'll publish it all at some point if you are interested?
Usually the most efficient way to iterate over an array collection in Javascript is to stick to the native for loop. The reason I say "usually" is that the implementation es down to each unique browser's implementation of javascript so there is no absolute definitive answer.
There's a nice post at http://solutoire./2007/02/02/efficient-looping-in-javascript/ which covers the performance of each of the main iteration methods and empirically es to the same conclusion.
If you don't need to maintain order, then the best way is to a regular object, and index by task id. That gives you O(1)
access.
var tasks = {
'2': {
id: 2,
name: 'Random Task',
pleted: 0
},
...
}
If you also need ordering maintained, then write an OrderedMap "class" that maintains the order by creating an array of task ids, but the actual tasks will still be stored in an object indexed by task id. So essentially you would have:
// internal API (to help maintain order)
taskIDs = [a, b, c, ..];
// internal API (for actual storage)
tasks = {
a: { .. },
b: { .. },
};
// external API for iterating objects in order
forEach(fn);
// external API for accessing task by ID
get(id);
The outside world can be ignorant of how you maintain order as long as you provide a nice encapsulated way of iterating these in order, and accessing them by task id.
If you need reference for implementing such a class, see the source for LinkedMap from Google Closure Library.
Just a little more food for thought, this is what I ended up with:
this.find = function (test) {
var results = [];
for (var i = 0,l = this.tasks.length; i < l; i++) {
var t = this.tasks[i];
if (eval(test)) {
results.push(this.tasks[i]);
}
}
return results;
}
this allows me to do a simple tasks.find('t.id == 2') or tasks.find('t.pleted == 1');
If id is unique (and mostly continuous) you can do a one time rearrange of the array so that array index reflects the id. If they're not unique, you can sort them and do a binary search.
But this would be useful only if you access the items by id from the array frequently, otherwise the overhead of sorting won't be worth it.
Is your array large? If not, you probably won't win many microseconds on optimizing it.
If it is large, you should really return a dictionary instead (As Matthew Flaschen mented), which uses the task's ID as key. In this way you'll get constant time lookup (atleast if the javascript implementation is optimal).
Just use a ordinary PHP associative array, and run it through json_encode or whatever you're using.
//Assume you have your original Array named $tasks:
$dictionary = Array();
foreach($tasks as $task)
$dictionary[$task->getID()] = $task;
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744229204a4564160.html
评论列表(0条)