Knockout Can I get around this computed loop? - javascript

I have the following structure for a bunch of objects in my viewmodel
I have an underlying array filled with objects that have ko.observable items in.
Ex: selections = [{Legs:{'0':ko.observable(12)}}, {Legs:{'0':ko.observable(0)}}]
What I am trying to achieve is that when a user clicks on a checkbox, that should toggle the Selected value of that Runner. Now when that happens I would also like to update the Cache value to reflect the Runners selected state
Cache is used as binary storage 12 == 1100 == Checkboxes 3 and 4 are checked
Now all of that I can get to work no problem, I obviously don't need to even make Cache observable.
But, I also have a need to programatically change the Cache values, and I would like the checkboxes to reflect these changes automatically.
What is below sorta works, but creates a Loop, which knockout gracefully handles, but its results are unreliable and this slows things down.
How can I create this binding setup?
function Runner(name, odds, race, leg, post) {
var runner = {
Name: name,
Odds: odds,
Post: post,
Race: race,
Leg: leg,
Cache: selections[race].Legs[leg],
Selected: ko.observable(false),
Enabled: ko.observable(true),
Valid: true
};
runner.Check = ko.computed(function() {
if (!this.Enabled.peek() || !this.Valid ) return;
var checked = this.Selected();
var cache = this.Cache();
if (checked) {
this.Cache(cache | 1 << this.Post);
} else {
this.Cache(cache & ~(1 << this.Post));
}
}, runner);
return runner;
}
Edit
<input type="checkbox" data-bind="checked: Selected, enable: Enabled"/>

I had a moment of clarity after writing my question. But I think its a good question none the less so rather than changing or removing my question ill just post my newest solution and get some critique hopefully.
So in the end I forgo the Selected value entirely
Note The this.Post + 1 is specific to my needs, its not needed normally, I simply wish to leave the first bit unused for future use.
runner.Check = ko.computed({
read: function() {
var cache = ko.utils.unwrapObservable(this.Cache); //Edit 1
return cache & 1 << (this.Post + 1);
},
write:function(value) {
var cache = this.Cache();
if (!this.Enabled.peek() || !this.Valid || this.Post === -1) return;
var mask = 1 << (this.Post+1);
if(value === !(cache & mask)){ //Edit 2
this.Cache(value ? cache | mask : cache & ~mask);
}
}
}, runner);
One bad thing about doing things this way is that if I have 20 runners who all use the same Cache, then when a user selects 1 of them all 20 will re-check themselves...
For my specific case a future change may be removing the Peek on Enabled, and performing a check that says if !Enabled then turn that bit off by default rather than possibly allowing a Disabled Checked checkbox.
Edit
Changed 'read' function to use unwrapObservable() in case the Cache is cleared by ways of the observable being deleted/removed elsewhere.
Edit 2
While answering a comment in the original question I realized that to help prevent some redundant calls I could add a check to see if the bit's value is already equal to value and if so do nothing, so if programatically I try to turn on a bit that is already on then it won't fire the computed since nothing has actually changed.

Related

Unable to read a true when using array value

UPDATE(11 Aug 22): Per request from Ruben - The checkboxes are placed next to a column of items using .insertCheckboxes(). They are checked when onEdit(e) is invoked by any entry in the checkbox column. Temporarily the checkbox status is listed next to each item to ensure that the checkbox value is changing. The desired outcome is to capture which checkbox is true so that item can be edited on the associated data entry form. The non-working code is part of a if/else statement. The if works fine, which indicates to me that the logic is OK:
if (newAssetBox === true) {
gatherAsset();
}
But the else statement does NOT work. As you can see below, it is using a counter thru an array to get and list the checkbox value. I have removed the // lines from the original posting for clarity.
Hope this helps better understand the problem.
ORIGINAL POST:
In this function the first if for newAssetBoxs() works just fine.
But if (theCheckedBoxs[count] === true) does not work (the block of code is temporary for trouble shooting purposes). The function is called by an OnEdit(). I have tried many ways and am totally frustrated.
You can see in the second block of code below that I can display the value of the checked box as true just fine (the boxs are between the TRUE/FALSE and the descriptive text) . Please offer some suggestions. Thanks
function checkTheBoxs() {
assetEntryForm.getRange("F2").clearContent();
if (newAssetBox === true) {
gatherAsset();
} else {
for (count = 0; count < 20; count++) {
assetEntryForm.getRange(count + 3, 10, 1, 1).setValue(theCheckedBoxs[count]);
if (theCheckedBoxs[count] === true) {
assetEntryForm.getRange("F2").setValue('Found a True');
} else {
editAsset();
}
}
}
The following block is a partial from the form page. The checkbox, not shown, but there on the form between TRUE and XLR is the only one checked.
FALSE AC / Power cables
TRUE XLR type cable
FALSE Multi Pair cables
FALSE NL4 cable
FALSE NL8 speaker cables
FALSE L14-30 10/4 cable
FALSE Behringer S16 Digital Snake with 100 Foot DuraCat6 Cable
I finally returned to this problem and logger.logged the theCheckedBoxs[count] to discover that it is actually a 2d array (why I am not sure). I was getting [true} instead of true, so I searched around and found that flat() will convert 2D to 1D and bingo, now I find my true with theCheckedBoxs.flat()[count] and life is good again...

How to solve problems of performance in the clearFilter() funcion in Sencha Touch?

I am working in a Sencha Touch application and when I use "clearFilter()" I am having a big efforts in terms of performance... For example, when I am writing in the searchfield and following rule specified in the filter (from the second character) I am waiting a second for to write the next character.. What is happening?
Currently my implementation is this:
store.clearFilter();
if (queryString && queryString.length > 2) {
var thisRegEx = new RegExp(queryString, "i");
store.filterBy(function (record) {
return (thisRegEx.test(record.get('customerId')) ||
thisRegEx.test(record.get('customerName')) ||
thisRegEx.test(record.get('customerAddress')));
}, this);
}
And it is working but with the problems indicated.
How to solve this of the right way?
The clearFilter has the suppressEvent argument:
true to clear silently without firing the refresh event.
So try store.clearFilter(true).
First of all, how many records are there in the store? The number of records can affect this very much.
To increase performance, you should combine those 3 fields in 1 another field so that you can search in one column with one regexp. 3 regular expression may be expensive for each record. This way, you can also use filter method, instead of filterBy.
Lastly, i'd prefer using buffer option for the listener here to avoid giving hard time to the typer for every single key down. For example:
xtype: 'textfield',
listeners: {
keyup: {
buffer: 500, // 500ms
fn: function(){
// filter code
}
}
}

Generate multiple checkboxes from Javascript array?

My jsfiddle will help explain things better than I ever can >< http://jsfiddle.net/L65QD/17/
I've got two select boxes, when you select something from the first select it enables the second. I have quite a few arrays that I'm using as sort of a fake database.
What I need to happen is that depending on what is selected in profile_select it needs to generate checkboxes for every PRIVILEGE_CODE it has, however the checkboxes must be generated with SEC_PRIVILEGES.Name next to them instead of the actual PRIVILEGE_CODE and they must be generated in the correct DIV. Since it's so hard to explain I made a JSFiddle which just about summarizes it http://jsfiddle.net/L65QD/17/
If my instructions aren't clear:
Depending on what profile is selected in the PROFILE_SELECTION
Needs to generate some checkboxes based on what PRIVILEGE_PROFILES.PRIVILEGE_CODES it has
However the checkboxes must have the name from SEC_PRIVILEGES next to them instead of the code, so PRIVILEGE_CODES = Unique_Code
Checkboxes are generated in either the DA div or the MR div based on what Group_Code they have in SEC_PRIVILEGES (this bit really confuses me, can you make it so a DIV ID can be equal to something from an array?) However to generate them in DA or MR it can't really be an IF because my fiddle is just an example and I'd actually have about 30 different codes so I couldn't do 30 IF statements.
This is the method I was experimenting with but it doesn't really make sense and is probably not even close to being on the right lines:
$(document).on('change', '#select_profile', function () {
var Select = $("#select_profile option:selected").text();
$("#apps").html;
for (var i = 0; i < SEC_Privileges.length; i++) {
if (SEC_Privileges[i].Unique_Code == //something?) {
$('#DA').html("<b>lol</b>");
}
}
});
So that's pretty simple:
Correct this fatal error: Array literals are written in square bracket notation ([], not ()). When you log the PRIVILEGE_PROFILE[0].PRIVILEGE_CODE you'll see only the first code is logged as the key's value.
Building the function: Consider what you need:
When a user changes company, all checkboxes must be reset
When a user changes profile, all checkboxes must be reset, then changed accordingly
When 'None' is selected in either dropdown, all checkboxes must be reset
Result: http://jsfiddle.net/kevinvanlierde/L65QD/19/
Some conventions:
Please choose one naming convention and stick with it. The more common ones are lowercase_underscore or CamelCase. You can opt for uppercase, but don't mix them (easier readability). I've had several errors just because I wrote the names incorrectly.
Declare your variables at the start of your function, assign them further on.
Also want to add that if I were to have control over the object's structure, I would probably opt for a more hierarchical tree/ JSON-like structure, eg instead of your current object, do:
var SEC_Privileges = {
'DA': {
'name': 'Dispatch App',
'accesses': {
'DAAccess': 'Access',
'DASuper': 'Supervisor'
}
},
'MR': {
'name': 'MyRoster',
'accesses': {
'MRAccess': 'Access',
'MRSuper': 'Supervisor'
}
}
}
Because the object keys are themselves values, you can use them to build your UI, eg to get the full name of your MRAccess you could do something like SEC_Privileges.MR.name + SEC_Privileges.MR.accesses.MRAccess to get MyRoster Access
There is different ways to approach this but the amount of Privileges would always be the same?. Depending on what your SEC_privileges is if its JSON array then you could loop through that array and access the code and the description. You would then want to validate the selected privileges again the whole set and say something like:
var array = ('one','two','three');
if($.inArray(SEC_privileges[i].Unique_code, array))
{
$('#DA').html("<input type='checkbox' id='"+i+"' value='"+SEC_privileges[i].Unique_code+"' checked/>"+SEC_privileges[i].Unique_desc);
}
else
{
$('#DA').html("<input type='checkbox' id='"+i+"' value='"+SEC_privileges[i].Unique_code+"'/>"+SEC_privileges[i].Unique_desc);
}
A ticked value is done by adding the word checked as part of the html input object. Like illustrated above

Form handling and validation in pure JavaScript

My intention is to get your thoughts and criticism about the script below, as regards the algorithm's design, performance and cross-browser compatibility.
I have just started getting into JavaScript having missed out on its awesomeness for quite a while. My background and experience is in developing C/C++/PHP based RESTful backends.
In order to understand the language and the right way of using it, I decided to do something which I am sure has been done many times before. But learning to use a new language and paradigm often entails pain anyway.
This is my attempt to create a normal form processing and validation script/ function.
In order to reduce complexity and keep code simple/clean, I decided to use HTML5 Custom Data Attributes (data-*) to assign metadata for each element in the form:
Data-Required: True or False. If set to true, this parameter makes the form-field required and so it cannot be empty. A value set to false indicates that the field is optional. Default is false.>
Data-Type: Type of validation to be performed. Examples include 'email', 'password', 'numbers' or any other 'regexp'.
A fairy simple example of such a form would be:
<form action="postlistings" id="postlistings" enctype='multipart/form-data' method="post" class="postlistings">
<ul class="login-li">
<li>
<input class="title" name="title" type="title" id="title" data-required="true" data-type="title"></a>
</li>
<li>
<textarea name="body" id="elm1" class="elm1" name="elm1" data-type="body" data-required="true" >
</textarea>
</li>
<li>
<span class="nav-btn-question">Add Listing</span>
</li>
</ul>
</form>
Reminder: This is my first piece of JavaScript code.
The idea is to call Form while passing the form name to retrieve and validate all the field values in one loop for performance. The validation involves two steps as can be guessed from the Data-* attributes described above:
i. Check for required form fields.
In case the values fail to meet step 1 requirement, an error message from configuration is pulled for the specific form value. Thus, for all values that fail to meet this requirement, an array of error messages are collected and passed on to the View.
ii. Perform respective validations.
Validations are only performed if all the values passed step 1. Otherwise, they follow the same steps as indicated in 1 above.
function Form(){
var args = Array.prototype.slice.call(arguments),
formName = args[0],
callback = args.pop(),
userError = [{type: {}, param: {}}],
requiredDataParam = 'required',
typeDataParam = 'type',
form = document.forms[formName],
formLength = form.length || null,
formElement = {id: {}, name: {}, value: {}, required: {}, type: {}};
function getFormElements(){
var num = 0;
var emptyContent = false;
for (var i = 0; i < formLength; i += 1) {
var formField = form[i];
formElement.id[i] = inArray('id', formField) ? formField.id : null;
formElement.name[i] = inArray('name', formField) ? formField.name : null;
formElement.value[i] = inArray('value', formField) ? formField.value : null;
formElement.required[i] = getDataAttribute(formField, requiredDataParam);
formElement.type[i] = getDataAttribute(formField, typeDataParam);
if (formElement.required[i] === true){
if(!formElement.type[i]) {
error('Validation rule not defined!');
}
else if (!formElement.value[i]) {
userError[num++] = {'type': 'required', 'param': form[i]};
emptyContent = true;
}
}
if (emptyContent === false) {
// Perform validations only if no empty but required form values were found.
// This is so that we can collect all the empty
// inputs and their corresponding error messages.
}
}
if (userError) {
// Return empty form errors and their corresponding error messages.
}
return formElement;
};
// Removed the getFormParam function that was not used at all.
return {
getFormElements: getFormElements
}
};
Two outside functions that are used in the JS script above (from JQuery source):
var inArray = function(elem, array){
if (array.indexOf){
return array.indexOf(elem);
}
for (var i = 0, length = array.length; i < length; i++){
if (array[i] === elem){
return i;
}
}
return -1;
}
// This is a cross-platform way to retrieve HTML5 custom attributes.
// Source: JQuery
var getDataAttribute = function(elem, key, data) {
if (data === undefined && elem.nodeType === 1) {
data = elem.getAttribute("data-" + key);
if (typeof data === "string") {
data = data === "true" ? true :
data === "false" ? false :
data === "null" ? null :
!CheckType.isNaN ? parseFloat(data) :
CheckType.rbrace.test(data) ? parseJSON(data) :
data;
}
else {
data = undefined;
}
}
return data;
}
An example of Config Error messages can be set as follows:
var errorMsgs = {
ERROR_email: "Please enter a valid email address.",
ERROR_password: "Your password must be at least 6 characters long. Please try another",
ERROR_user_exists: "The requested email address already exists. Please try again."
};
As I post this for your review, please ignore any styling conventions that I might not have followed. My intention is to get your expert reviews on anything I should be doing different or could do better concerning the code itself, and the algorithm.
Besides the styling conventions, all criticism and questions are welcome.
First I'd like to clear up a common misconception. Forgive me if you already understand this clearly; maybe it will be helpful for someone else.
Learning and using jQuery or a similar library does not preclude or conflict with learning the JavaScript language. jQuery is simply a DOM manipulation library which takes away many of the pain points of using the DOM. There's plenty of room to learn and use JavaScript, the language, even if you use a library to abstract away some of the DOM details.
In fact, I would argue that using the DOM directly is likely to teach bad JavaScript coding habits, because the DOM is very much not a "JavaScript-ish" API. It was designed to work identically in JavaScript and Java and potentially other languages, and so it completely fails to make good use of the features of the JavaScript language.
Of course as you said, you're using this as a learning exercise; I just don't want you to fall into the trap that I've seen many people fall into of thinking, "I don't want to learn jQuery, because I want to learn JavaScript instead!" That's a false dichotomy: you have to learn JavaScript in either case, and using jQuery for the DOM doesn't interfere with that at all.
Now some details...
While it's OK to quote property names in an object literal and when you reference the properties, it's customary - and more readable - not to quote them when they are valid JavaScript names. e.g. in your formElement object
formElement = { id: {}, name: {}, value: {}, required: {}, type: {} };
(there was a missing semicolon at the end there too)
and where you use the names you can do:
formElement.id[i] = ...
formElement.name[i] = ...
etc.
Don't run your loops backwards unless the program logic requires it. It doesn't make the code faster except possibly in the case of an extremely tight loop, and it makes it unclear whether you're just prematurely optimizing or actually need the backwards loop.
Speaking of optimization, that loop has several inArray() calls. Since each of those loops through an array, that could be more of a performance impact than the outer loop. I imagine these arrays are probably pretty short? So performance wouldn't matter at all anyway, but this is something to think about in cases where you have longer arrays and objects. In some cases you can use an object with property names and values for a faster lookup - but I didn't look closely enough at what you're doing to suggest anything.
In any case, you're using inArray() wrong! But not your fault, that is a ridiculously named function in jQuery. The name clearly suggests a boolean return value, but the function returns the zero-based array index or -1 if the value is not found. I strongly recommend renaming this function as indexOf() to match the native Array method, or arrayIndex(), or some such.
That same loop has form[i] repeated numerous times. You could do this at the top of the loop:
var field = form[i];
and then use field throughout, e.g. field.id instead of form[i].id. This is generally faster, if it matters (which it probably doesn't here), but more importantly it's easier to read.
Do not use strict boolean comparisons like if( foo === true ) and if( bar === false) unless you really need to - and those cases are rare. The code sends a signal to the reader that there is something going on that's different from the usual boolean test. The only time these particular tests should be used is when you have a variable that may contain a boolean value or may contain some other type of value, and you need to distinguish which is which.
A good example of a case where you should use tests like these is an optional parameter that defaults to true:
// Do stuff unless 'really' is explicitly set to false, e.g.
// stuff(1) will do stuff with 1, but stuff(1,false) won't.
function stuff( value, really ) {
if( really === false ) {
// don't do stuff
}
else {
// do stuff
}
}
That specific example doesn't make a lot of sense, but it should give you the idea.
Similarly, an === true test could be used in a case where need to distinguish an actual boolean true value from some other "truthy" value. Indeed, it looks like this line is a valid case for that:
if (formElement['required'][i] === true){
given that if (formElement['required'][i] comes from the getDataAttribute() function which may return a boolean or other type.
If you are just testing for truthiness, though - and this should be most of the time - simply use if( foo ) or if( ! foo ). Or similarly in a conditional expression: foo ? x : y or !foo ? x : y.
The above was a long-winded way of saying that you should change this:
if (empty_content === false) {
to:
if (!empty_content) {
Your getFormParam() function goes to some work to convert an undefined result to null. There is usually no reason to do this. I don't see any place where that function is called, so I can't advise specifically, but in general you'd be testing for truthiness on something like this, so null and undefined would both be treated as false. Or in cases where you do need to distinguish null/undefined from other values (say, an explicit false), you can easily do it with != null or == null. This is one case where the "looser" comparison performed by == and != is very useful: both null and undefined evaluate the same with these operators.
You asked to ignore coding style, but one little suggestion here: You have a mix of camelCaseNames and names_with_underscores. In JavaScript, camelCaseNames are more idiomatic for function and variable names, with PascalCaseNames for constructor functions. Of course feel free to use underscores where they make more sense, for example if you're writing code that works with database columns in that format you may want your variable names to match the column names.
Hope that helps! Keep up the good work.
Update for your new code
I'm having a bit of trouble following the logic in the code, and I think I know part of the reason. It's a combination of naming conventions and inside-out objects.
First, the name formElement is really confusing. When I see element in JavaScript, I think of either a DOM element (HTMLElement) or an array element. I'm not sure if this formElement represents one or the other or neither.
So I look at the code to figure out what it's doing, and I see it has id:{}, name:{}, ... properties, but the code later treats each of those as an Array and not an Object:
formElement.id[i] = ...
formElement.name[i] = ...
formElement.value[i] = ...
formElement.required[i] = ...
formElement.type[i] = ...
(where i is an integer index)
If that code is right, those should be arrays instead: id:[], name:[], ....
But this is a red flag. When you see yourself creating parallel arrays in JavaScript, you're probably doing it wrong. In most cases you're better off replacing the parallel arrays with a single array of objects. Each of the objects in that array represents a single slice through all your parallel arrays, with a property for each of the previous arrays.
So, this object (where I've made the correction from {} to [] to match its current use):
formElement = { id: [], name: [], value: [], required: [], type: [] };
should be:
formInfo = [];
and then where you have the code that goes:
formElement.id[i] = ...;
formElement.name[i] = ...;
formElement.value[i] = ...;
formElement.required[i] = ...;
formElement.type[i] = ...;
It should be:
var info = {
id: ...,
name: ...,
value: ...,
required: ...,
type: ...
};
formInfo.push( info );
and adjust the rest of the code to suit. For example:
formElement.required[i]
would be:
formInfo[i].required
or even simpler since it's in the same function:
info.required
And note: I'm not saying info and formInfo are great names :-) they are just placeholders so you can think of a better name. The main idea is to create an array of objects instead of a set of parallel arrays.
One last thing and then I'm out of time for now.
That getDataAttribute() function is a complicated little piece of work. You don't need it! It would be simpler would just call the underlying function directly where you need it:
var info = {
...
required: formField.getAttribute('data-required') === 'true',
type: formField.getAttribute('data-type')
};
This also gives you full control of how the attributes are interpreted - as in the === 'true' test above. (This gives you a proper boolean value, so when you test the value later you don't have to use === true on it.)
On a stylistic note, yes, I did hard code the two 'data-xxxx' names right there, and I think that's a better and more clear way to do it.. Don't let your C experience throw you off here. There's no advantage to defining a string "constant" in this particular case, unless it's something that you want to make configurable, which this isn't.
Also, even if you do make a string constant, there's a minor advantage to having the complete 'data-whatever' string instead of just 'whatever'. The reason is that when somebody reads your HTML code, they may see a string in it and search the JS code for that string. But when they search for data-whatever they won't find it if the data- prefix is automagically prepended in the JS code.
Oh, I forgot one last thing. This code:
function Form(){
var args = Array.prototype.slice.call(arguments),
formName = args[0],
callback = args.pop(),
is working way too hard! Just do this instead:
function Form( formName, callback ) {
(and keep the var for the remaining variable declarations of course)
I cannot add comments yet so here is a little tip. I would separate the getFormElements() into smaller private functions. And I would add the errorMsgs to the Form function.
But for a first script in JavaScript, it is very impressive. This is actually the real reason I respond. I think it deserves more upvotes, and I would be very interested in a JS ninja responding to this question.
Good luck!

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.

Categories

Resources