Weirdness when modifying massive json file/array in Node.js - javascript

I am working with a massive json file (almost 60 MB) that i am trying to remove all entries in it where volume = 0. The format of the array is
{
"date": 1424373000,
"high": 0.33,
"low": 225,
"open": 0.33,
"close": 225,
"volume": 0.999999,
"quoteVolume": 0.00444444,
"weightedAverage": 225
}
To do this I am using this code.
fs.readFile('JSONFiles/poloniexBTCDataFeb19|2015-July2|2018.json', function read(err, data) {
if (err) {
throw err;
}
rawdata = JSON.parse(data);
rawdata.forEach(function(val, index, array) {
if (rawdata[index].volume == 0) {
rawdata.splice(index, 1)
}
})
});
The problem with this is that it only deletes about half of the entries with this characteristic (60k/108k). The way I fixed this was to use a for loop which runs the code 9 times, which deletes them all, but this causes the code to take significantly longer cause the whole json file has about 360k entries and it has to check each one with that if statement. I was wondering if there was any way to do this where it actually deletes them all without having to use a for loop in this manner?
EDIT: I have realized that I do not need this code in the first place so nevermind but thanks for all the answers. I hope this helps someone else when they hit a simmilar issue.

The problem is, you are mutating the array rawdata. Let's take an example array [e1, e2, e3, e4] and the code,
var arr = ['e1', 'e2', 'e3', 'e4']
arr.forEach(function(elem, idx){
console.log('checking elem', elem);
if (elem === 'e2'){
arr.splice(idx, 1)
}
});
console.log('\nAfter iteration', arr);
As you can see, I am removing e2 when I encounter it. This affects the actual array and the element which is getting replaced for it, will not be inspected (as forEach iteration already visited element at that index). In the above code, e3 did not get checked. So, it is advised to not mutate array in forEach iteration.
You can do like,
rawdata.slice().forEach(function (val, index, array) {
if (rawdata[index].volume == 0) {
rawdata.splice(index, 1)
}
});
Here slice() will make a new array and mutating your original rawdata will not affect the iteration.

You are splicing the records, that might be taking time.
Instead of the forEach, try this:
var filteredData = rawdata.filter(function (val) {
return val.volume != 0
})

Your code is buggy and the error is quite common (iterating over an array while mutating it). The code is also very inefficient because for each element to delete will move all other elements by one place (the fact that you use splice doesn't mean the a loop is not done... there is still a loop behind the scenes to implement that function).
If you need to remove elements from an array in-place (i.e. you don't want to get a copy) a simple approach is using what I normally call a read-skip-write loop:
let wp = 0; // the "write pointer"
for (let x of data) {
if (keep(x)) data[wp++] = x;
}
data.length = wp; // trim unused space
PS: as a side note try to change your mindset about programming. If your first thought is that node is buggy then you're not going to get very far into coding. The reality is that bug is 99.99% of the times in your code... looking somewhere else won't make you a better programmer.

Related

Restricted JavaScript Array Pop Polyfill not working

I'm creating a few specific functions for a compiler I'm working on, But certain restrictions within the compiler's nature will prevent me from using native JavaScript methods like Array.prototype.pop() to perform array pops...
So I decided to try and write some rudimentary pseudo-code to try and mimic the process, and then base my final function off the pseudo-code... But my tests seem to fail... based on the compiler's current behavior, it will only allow me to use array.length, array element assignments and that's about it... My code is below...
pop2 = function(arr) {
if(arr.length>0){
for(var w=undefined,x=[],y=0,z=arr.length;y<=z;y++){
y+1<z?(x[y]=arr[y]):(w=arr[y],arr=x);
}
}
return w;
}
Arr = [-1,0,1,2];
// Testing...
console.log(pop2(Arr)); // undefined... should be 2
console.log(Arr); // [-1,0,1,2]... should be [-1,0,1]
I'm trying to mimic the nature of the pop function but can't seem to put my finger on what's causing the function to still provide undefined and the original array... undefined should only return if an initial empty array is sent, just like you would expect with a [].pop() call...
Anyone have any clues as to how I can tailor this code to mimic the pop correctly?
And while I have heard that arr.splice(array.length-1,1)[0]; may work... the compiler is currently not capable of determining splice or similar methods... Is it possible to do it using a variation of my code?
Thanks in advance...
You're really over-thinking [].pop(). As defined in the specs, the process for [].pop() is:
Get the length of the array
If the length is 0
return undefined
If length is more than 0
Get the item at length - 1
Reduce array.length by 1
Return item.
(... plus a few things that the JavaScript engine needs to do behind the scenes like call ToObject on the array or ensure the length is an unsigned 32-bit integer.)
This can be done with a function as simple as the one below, there's not even a need for a loop.
function pop(array) {
var length = array.length,
item;
if (length > 0) {
item = array[length - 1];
array.length -= 1;
}
return item;
}
Edit
I'm assuming that the issue with the compiler is that Array.prototype.pop isn't understood at all. Re-reading your post, it looks like arrays have a pop method, but the compiler can't work out whether the variable is an array or not. In that case, an even simpler version of this function would be this:
function pop(array) {
return Array.prototype.pop.call(array);
}
Try that first as it'll be slightly faster and more robust, if it works. It's also the pattern for any other array method that you may need to use.
With this modification, it works:
http://jsfiddle.net/vxxfxvpL/1/
pop2 = function(arr) {
if(arr.length>0){
for(var w=undefined,x=[],y=0,z=arr.length;y<=z;y++){
if(y+1<z) {
(x[y]=arr[y]);
} else {
(w=arr[y],arr=x);
break;
}
}
}
return w;
}
Arr = [-1,0,1,2];
// Testing...
console.log(pop2(Arr)); // 2
The problem now is to remove the last element. You should construct the original array again without last element. You will have problems with this because you can't modify the original array. That's why this tasks are maded with prototype (Array.prototype.pop2 maybe can help you)

Most efficient way to delete from array?

I have an array containing particles (fire, blood, smoke, etc.) in an HTML5 game. All particles have an expiry/lifespan. I'm creating up to 100 particles per frame at 60fps so I want to keep this array as clean as possible so I can loop through it efficiently.
I have heard it's better to use 'splice' rather than 'delete' to remove elements from an array. This makes sense to me as I'd rather not loop through keys of the array that are blank (that 'delete' leaves behind).
However, I tested this out and have a higher, more consistent frame rate if I 'delete' keys rather than splicing them to remove expired particles. The downside is the longer the game runs the longer my particles array gets.
Is there a better solution to this?
If the order of the items in the array doesn't matter, then simply assign the last item in the array to the one you want to overwrite and then delete it by reducing the .length.
function unordered_remove(arr, i) {
if (i <= 0 || i >= arr.length) {
return;
}
if (i < arr.length - 1) {
arr[i] = arr[arr.length-1];
}
arr.length -= 1;
}
This is much faster because it doesn't need to reindex and is good for situations where the order doesn't matter.
When you use delete on an array element, all you are actually doing is setting that array element to undefined. The array will still have the same length. When you use splice, you actually remove that element entirely. The element is removed, and everything after that element is shifted down 1 index.Of the two, delete is going to be faster since your array doesn't have to re-index.
As for performance, if leaving the deleted elements as undefined works, then that is probably the best way to do it. If you are concerned about the array length growing too long, or maybe have to search that array frequently and want to reduce overhead, you could periodically filter out the undefined elements like so:
function filterArr() {
myArr = myArr.filter(function(v) {
return typeof v !== 'undefined';
});
}
var interval = setInterval(filterArr, 5000);
This will give you the best of both worlds. When you need to remove the particles, you use delete to set the elements to undefined, which is faster than removing them in place. Every now and then, you remove them in place to keep your array size lower.
You could improve upon that depending on your requirements. Good luck :)
You'll have way higher performances by packing the array by yourself : less operations AND no need to dispose current array and create a new one (like Array.filter does), so much less garbage collection.
function packArray(tgtArray) {
if (!tgtArray || !tgtArray.length) return;
var srcIndex = 0;
var dstIndex = 0;
var arrayLength = tgtArray.length ;
do {
var currentItem = tgtArray[srcIndex];
if (currentItem.alive) {
if (srcIndex != dstIndex) {
tgtArray[dstIndex] = currentItem ;
}
dstIndex++;
}
srcIndex++;
} while (srcIndex != arrayLength) ;
dstIndex--;
tgtArray.length = dstIndex > 0 ? dstIndex : 0 ;
}

get sub array of array javascript

I have a array in javascript and I want a sub array of the array with element which are at position n*3, n=0,1,2.. for example if:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12]
var subArr = [1,4,7,10]
Edit : any soln without looping.
Here's an example of a fancy way :
var brr = [1,2,3,4,5,6,7,8,9,10,11,12].filter(function(_,i){ return !(i%3) })
But a simple loop would have been as good (and would have been compatible with IE8). note that filter, even if it's not visible, does loop over the array. You can't avoid a loop (at least for an arbitrary sized array) even if you may disguise it.
Here's how you would do it with a standard loop :
var brr = [];
for (var i=0; i<arr.length; i+=3) brr.push(arr[i])
Performance is rarely a concern on such operations client side but you might find important to know that the for loop is much faster here : http://jsperf.com/looporfilter
In order to operate on a set of data of size n, m times, where m > 1, how would you avoid iteration? Really, there is no way unless you use a set of O(1) operations like this:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
var subarr = [];
subarr.push(arr[0]);
subarr.push(arr[3]);
subarr.push(arr[6]);
subarr.push(arr[9]);
Here is a structural recursion (which can be represented by a loop, and does technically loop).
var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
var subarr = [];
(function recur(n){
if( n >= arr.length ) return;
subarr.push(arr[n]);
recur(n+3);
})(0);
To note: a straight for loop will always be faster. In an expansion of #dystroy's jsperf, this recursion ran slower than the for loop, but faster than the filter. http://jsperf.com/looporfilter/2
just for kicks, i searched for a way to actually do it without a loop like the OP wanted.
without using a loop, it's tough.
the closest i could manage gets the right numbers, but converts them to Strings instead of numbers.
var r=[1,2,3,4,5,6,7,8,9,10,11,12,13,14];
alert( "".replace.call(r+",-0,-0,-0", /(\d+),\d+,?(\d+,|$)/g, "$1,")
.replace(/(,?\-0){1,4}$/g,"")
.split(",") );
//shows: 1,4,7,10,13
if you need strong numbers, it's easy, but i am not sure if adding .map(Number) after .split(",") would constitute a loop in your book, but this is the only version that actually finds the desired results without a loop.
this also only works on positive integers as coded.
again, more for fun than something i would recommend using; don't be afraid of loops...
Here's a solution with no loop:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
// pickInterval is a function that automatically picks every "n"
// elements from an array, starting with the first element
var subArr = pickInterval( arr, 3 );
// now subArr is [1,4,7,10]
Simple, isn't it? And not a loop in sight.
Ah, but you ask, "What's the catch? You haven't implemented that pickInterval() function, have you? I bet there's a loop in it."
And you're right. Even if we write our pickInterval() function using some other function that doesn't look like a loop, that function will have a loop in it. And if that one just calls yet another function, eventually you will find a loop.
It may be turtles all the way down, but there's a loop underneath them all.
So, to implement pickInterval(), we could use either approach from #dystroy's answer. We can put the loop right inside the function:
function pickInterval( array, interval ) {
var result = [];
for( var i = 0, n = array.length; i < n; i += 3 )
result.push( array[i] );
return result;
}
Or we can use .filter():
function pickInterval( array, interval ) {
return array.filter( function( _, i ){
return !( i % 3 );
});
}
Of course there's still a loop here, down inside .filter(). It's just been hidden from us in the very same way that pickInterval() hides any loop from its caller.
And that's the real point. Use .filter(), use a for loop, use whatever you want, as long as you encapsulate it inside a function. Then the inner workings of that function don't matter so much. If you like the for loop because it's fast and easy to understand, use that. If you like the filter() version because it's interesting and elegant, use that. If you later need to use it on a very large array and it's running slow, you can replace it with the for loop version without affecting the code that uses pickInterval().
Whatever code you write for this or for something like it, don't put it inline. Make a function.

Delete certain properties from an object without a loop

I'm trying to find the most efficient way of deleting properties from an object whose properties of commentCount and likeCount are both equal to 0. In the following example, Activity.3 would be removed. I don't want loop over them with a $.each() as that seems like it would take more time than necessary.
Activity = {
0 : {
'commentCount' : 10,
'likeCount' : 20
},
1 : {
'commentCount' : 0,
'likeCount' : 20
},
2 : {
'commentCount' : 10,
'likeCount' : 0
},
3 : {
'commentCount' : 0,
'likeCount' : 0
}
}
UPDATE
The circumstances of the creation of this object have come into question. To clarify, the Activity object can have up to 3 million properties inside of it. It's generated server side as an AJAX JSON response which is saved into memory. It includes more than just commentCount and likeCount that are used elsewhere, so I can't just not have the server not respond with things that have a 0 for both commentCount and likeCount.
Ah, the smell of premature optimization ^_^
How many of these objects do you have? How many do you need to clean them? If the answers are "less than 1 million" and "once or rarely", it's probably not worth to bother.
If you need a quick and optimal way, here is an idea: Create a new data structure and setters for the properties. Every time they are set, check whether they are both 0 and put them into a "kill" list.
That way, you just have to iterate over the kill list.
[EDIT] With several million objects and the need for a quick cleanup, a kill list is the way to go, especially when the condition is rare (just a few objects match).
Just write a function that updates these properties and make sure all code goes through it to update them. Then, you can manage the kill list in there.
Or you can simply delete the object as soon as the function is called to set both or the second property to 0.
I'm adding a second answer, because this solution comes from a completely different angle. In this solution, I attempt to find the fastest way to remove unwanted entries. I'm not aware of any way of doing this without loops, but I can think of several ways to do it with loops using jQuery as well as just raw javascript.
This jsperf shows all of the test cases side-by-side.
I'll explain each test and the caveats associated with each.
Raw JS: Slowest option. It looks like jQuery knows what they are doing with their $.each and $.map loops.
var obj;
for (var field in Activity) {
if (Activity.hasOwnProperty(field)) {
obj = Activity[field];
if (obj.commentCount === 0 && obj.likeCount === 0) {
delete Activity[field];
}
}
}
$.each: Tied for 2nd place. Cleaner syntax and faster than raw js loop above.
$.each(Activity, function(key, val){
if (val.commentCount === 0 && val.likeCount === 0) {
delete Activity[key];
}
});
$.map (Object version): Tied for 2nd place. Caveat: only supported in jQuery >= 1.6.
Activity = $.map(Activity, function(val, key){
if (val.commentCount === 0 && val.likeCount === 0) {
return null;
}
});
$.map (Array version): Fastest option. Caveat: You must use the $.makeArray function to convert your object to an array. I'm not sure if this is suitable for your needs.
var arrActivity = $.makeArray(Activity);
Activity = $.map(arrActivity, function(val, key){
if (val.commentCount === 0 && val.likeCount === 0) {
return null;
}
});
Conclusion
It looks like $.map is the fastest if you convert your object to an array using $.makeArray first.
This is just a starting-point, but how about something like this? Basically, it puts the Activities into buckets based on the sum of their likeCount and commentCount. It makes it easy to kill all of the Activities with no likes or comments, but I would assume there is a trade-off. I'm not sure how you are inserting these things and reading them. So, you'll have to decide if this is worth it.
var ActivityMgr = function(){
if(!(this instanceof ActivityMgr)){
return new ActivityMgr();
}
this.activities = {};
};
ActivityMgr.prototype.add = function(activity){
var bucket = parseInt(activity.commentCount, 10) + parseInt(activity.likeCount, 10);
if (this.activities[bucket] === undefined) {
this.activities[bucket] = [activity];
}
else {
this.activities[bucket].push(activity);
}
this.cleanse();
};
ActivityMgr.prototype.cleanse = function(){
this.activities[0] = [];
};
//Usage:
var activityMgr = new ActivityMgr();
activityMgr.add({
likeCount: 0,
commentCount: 10
});
EDIT:
After posting this, it becomes incredibly apparent that if you are adding items in this manner, you could just not add them if they have no likes or comments. My guess is that things aren't that simple, so please provide some detail as to how things are added and updated.

Improve performance of searching JSON object with jQuery

Please forgive me if this is answered on SO somewhere already. I've searched, and it seems as though this is a fairly specific case.
Here's an example of the JSON (NOTE: this is very stripped down - this is dynamically loaded, and currently there are 126 records):
var layout = {
"2":[{"id":"40","attribute_id":"2","option_id":null,"design_attribute_id":"4","design_option_id":"131","width":"10","height":"10",
"repeat":"0","top":"0","left":"0","bottom":"0","right":"0","use_right":"0","use_bottom":"0","apply_to_options":"0"},
{"id":"41","attribute_id":"2","option_id":"115","design_attribute_id":"4","design_option_id":"131","width":"2","height":"1",
"repeat":"0","top":"0","left":"0","bottom":"4","right":"2","use_right":"0","use_bottom":"0","apply_to_options":"0"},
{"id":"44","attribute_id":"2","option_id":"118","design_attribute_id":"4","design_option_id":"131","width":"10","height":"10",
"repeat":"0","top":"0","left":"0","bottom":"0","right":"0","use_right":"0","use_bottom":"0","apply_to_options":"0"}],
"5":[{"id":"326","attribute_id":"5","option_id":null,"design_attribute_id":"4","design_option_id":"154","width":"5","height":"5",
"repeat":"0","top":"0","left":"0","bottom":"0","right":"0","use_right":"0","use_bottom":"0","apply_to_options":"0"}]
};
I need to match the right combination of values. Here's the function I currently use:
function drawOption(attid, optid) {
var attlayout = layout[attid];
$.each(attlayout, function(k, v) {
// d_opt_id and d_opt_id are global scoped variable set elsewhere
if (v.design_attribute_id == d_att_id
&& v.design_option_id == d_opt_id
&& v.attribute_id == attid
&& ((v.apply_to_options == 1 || (v.option_id === optid)))) {
// Do stuff here
}
});
}
The issue is that I might iterate through 10-15 layouts (unique attid's), and any given layout (attid) might have as many as 50 possibilities, which means that this loop is being run A LOT.
Given the multiple criteria that have to be matched, would an AJAX call work better? (This JSON is dynamically created via PHP, so I could craft a PHP function that could possibly do this more efficently),
or am I completely missing something about how to find items in a JSON object?
As always, any suggestions for improving the code are welcome!
EDIT:
I apologize for not making this clear, but the purpose of this question is to find a way to improve the performance. The page has a lot of javascript, and this is a location where I know that performance is lower than it could be.
First and foremost you should measure and only act if there is a real performance concern. You need exact numbers like 200ms or 80% time is spent there. "It runs a lot" doesn't mean anything. The browser can loop very fast.
You can improve constant factors as others mentioned, like using a native for loop instead of jQuery.each. Chaching global variables won't help you too much in this case.
If you really want to improve efficency you should find a better algorithm than O(n). Assuming that you only use this data for finding elements matching a certain criteria you can use JS objects as hashes to achive a O(1) performance.
Just an example for you specific case:
var layout = {
"2": { "2,,4,131,10,0": ["40", "93"], "2,115,4,131,0": ["41"] },
"4": { ... },
...
};
It's fairly easy to generate this output in php, and then you just use a lookup to find ids matching your particular criteria.
IMHO, a simple hashmap index will probably work best. This does require you to loop over the data ahead of time, but the index can be easily appended to and cached.
Once the index is generated, this should be O(1) for lookups, and will handle multiple entries per key.
var layout = {
"2":[[...], ...],
"5":[[...], ...]
};
var index = {};
function makeKey(data) {
return data.join('_');
}
for(var l in layout) {
var cur = layout[l];
for(var i in cur) {
var item = cur[i];
var key = makeKey([item.p1, item.p2, ...]);
index[key] = index[key] || [];
index[key].push(item);
}
}
function find(attid, optid) {
var key = makeKey([attid, optid, 1, d_att_id, ...]);
return index[key]; //this is an array of results
}
My first suggestion would be to stop using $.each if you want to squeeze out every bit of performance you can. jQuery.each does a bit more than a traditional loop. Take a look at this jsFiddle with your browser's debugger running (i.e. Safari's/Chrome's web developer tools) and step through the fiddle until execution fully returns from jQuery.
For reference, the fiddle's code is:
var myArr = [{"foo":"bar"},{"answer":42}];
debugger;
$.each(myArr, function(k, v) {
console.log(k + ': ');
console.dir(v);
});​
Now run through the second version:
var myArr = [{"foo":"bar"},{"answer":42}],
i, j;
debugger;
for (i = 0, j = myArr.length; i < j; i += 1) {
console.log('myArr[' + i + ']: ');
console.dir(myArr[i]);
}​
Notice that there are far fewer operations being executed in the second version. So that's a tiny bit of performance gain.
Second, eliminate as many lookups outside of the local scope as you can. Even if you cache a reference to your global variables (boo!) then you can save a lot of time given that this loop will be executed possibly hundreds of times. So instead of:
function foo(a, b) {
if (a === globalA && b === globalB) {
// Do stuff
}
}
You'd do:
function foo(a, b) {
var gA = globalA,
gB = globalB;
if (a === gA && b === gB) {
// Do stuff
}
}
As for pairing down the conditional based on the object members, I'm not seeing much else that could be improved. The object properties you are checking are top level, and you're looking at local instances of each object (so the scope chain lookups are short).
Without knowing more about how this is actually supposed to work, those are the best recommendations I can make. However, I can make the guess that your idea of starting with simpler JSON data would be a big improvement. If you know what the layout, and its constraints, is, then requesting the specific details from the server would mean you don't have to check so many conditions. You could simply ask the server for the details that you actually need to implement and loop through those (to update the DOM or whatever).
I see that the you are searching by
5 fields: v.design_attribute_id,v.design_option_id,v.attribute_id,v.apply_to_options,v.option_id.
What you could do is add an extra field to the objects called "key" that is a composite of the values in those fields.
Here's an example
{
"key": "4_131_2_0_0" //i picked 0 to represent null, but you can pick any number
"id": "40",
"attribute_id": "2",
"option_id": null,
"design_attribute_id": "4",
"design_option_id": "131",
"width": "10",
"height": "10",
"repeat": "0",
"top": "0",
"left": "0",
"bottom": "0",
"right": "0",
"use_right": "0",
"use_bottom": "0",
"apply_to_options": "0"
}
Note though that you must normalize the length of each value.
Meaning that if one objects optionId is 1 and another object optionID is 566 you must represent
the first optionId as 001 in the key string.
With this field you can then sort the array on the server side before returning it to the client.
Then you can use a binary search to find the values on the client.
Using the binary search implementation located here
http://www.nczonline.net/blog/2009/09/01/computer-science-in-javascript-binary-search/
Your search function would look something like
function drawOption(attid, optid) {
var attlayout = layout[attid];
var needle = d_att_id + "_" + d_opt_id + "_" + attid + "_" + optid; //remember to normalize length if you have to
var idx = binarySearch(attlayout,needle);
var item;
if(idx !== -1){
item = attlayout[idx];
//do something
}
}
Another method you can try using this composite key idea is to have the server return
the layout objects in one big object mapped by
attid,v.design_attribute_id,v.design_option_id,v.attribute_id,v.apply_to_options,v.option_id
Then you can look up in O(1) time.
It would look something like
function drawOption(attid, optid) {
var needle = attid + "_" + d_att_id + "_" + d_opt_id + "_" + attid + "_" + optid; //remember to normalize length if you have to
var item = layout[needle];
if(typeof item !== "undefined"){
//do something
}
}
When trying to improve your code, it is always better to check which functions are taking time using firebug profiling. You can either profile by clicking on profile button in firebug's console panel and then run your code or using firebug's profiling commands in your code
From the code that you have given, only a few improvement points can be given.
$.each is slow compared to native looping solutions. For the best
looping solutions, check out this JsPref test
It would be better to change the JSON to use arrays instead of object literals. It is said to be more faster to retrieve values.
I have experience to such issue before, my js array of objects consist of 8 thousands record and more.
My experience is not about the performance, but the readability, maintainability, scalable of the codes.
hence I developed an JS Object Query Library 2 years ago: JSOQL
http://code.google.com/p/jsoql/
It works like SQL to allow you query your js array of objects with syntax similar to SQL.
The example usage is something like this, I cant really remember, but you can download the example usage in the download tab.
new JSQOL().Select([field1, field2, field3 ...]).From({ ... }) .Where(fn) .Offset(int) .Limit(int) .Get();
Note:
{...} is your array of objects, or an object it self.
Hope it helps, you can send me message if you need more information.
It's not going to work everywhere but your problem sounds like something that can be done with webworkers
Another thing I would look at if you dont have webworkers is trying not to block the ui to long. If you can chunk it into bits of about 40ms and then setTimeout the next chunck for just a few ms later the user will have a more pleasant experience. This needs a little fiddling but users will start to notice stuff when something takes longer than somewhere between 50 and 100ms
Have you considered using the jQuery grep function?
jQuery grep
And jquery grep on json object array for an example.
Here is one technique that will probably yield better performance at the expense of using a bit more memory.
I'll leave my code examples simple just to illustrate the concept.
First, you'll want to pre-process your JSON data into some additional arrays that act as indexes. Here is an example of what the final arrays might look like after pre-processing:
var layouts_by_attribute = {
// attribute_id => array(layouts)
2: [40, 41, 44],
5: [326]
};
var layouts_by_design_attribute_id = {
// design_attribute_id => array(layouts)
4: [40, 41, 44, 326]
};
Finding a layout by attribute is now very quick:
function findByAttribute(attribute_id) {
return layouts = layouts_by_attribute[attribute_id];
}
function findByDesignAttribute(design_attribute_id) {
return layouts = layouts_by_design_attribute[design_attribute_id];
}

Categories

Resources