Efficient Javascript Array Lookup - javascript

If I have a whitelist of strings that I want to check everything the user inputs into my javascript program, what's the most efficient way to do that? I could just have an array and loop through it until a match has been found but that's O(N). Is there an yway to do it that's better and doesn't involve any sort of key value lookup, just checking to see if that value exists?
EDIT: I guess what I'm looking for is the equivalent of a set in C++ where I can just check to see if a value I'm given already exists in the set.

Just make it a simple js object instead of an array.
var whitelist = {
"string1":true,
"string2":true
}
and then you can just check if(whitelist[str]) to check if its available.
Or use if(str in whitelist).
I expect that the first will have slightly better performance (I haven't verified that), but the second is more readable and makes the purpose clear. So its your choice of which is a better fit.

Sort the array, use binary search for the look-ups.
Or
Create an object where the key is the item and use the hash look-up whitelist[value] != undefined

I think you'll find that key-value lookup is almost identical in performance to some kind of set implementation without values. (Many standard libraries actually just implement a set using a map)

Related

Realm-JS: Performant way to find the index of an element in sorted results list

I am searching for a perfomant way to find the index of a given realm-object in a sorted results list.
I am aware of this similar question, which was answered with using indexOf, so my current solution looks like this:
const sortedRecords = realm.objects('mySchema').sorted('time', true) // 'time' property is a timestamp
// grab element of interest by id (e.g. 123)
const item = realm.objectForPrimaryKey('mySchema','123')
// find index of that object in my sorted results list
const index = sortedRecords.indexOf(item)
My basic concern here is performance for lager datasets. Is the indexOf implementation of a realm-list improved for this in any way, or is it the same as from a JavaScript array? I know there is the possibility to create indexed properties, would indexing the time property improve the performance in this case?
Note:
In the realm-js api documentation, the indexOf section does not reference to Array.prototype.indexOf, as other sections do. This made me optimistic it's an own implementation, but it's not stated clearly.
Realm query methods return a Results object which is quite different from an Array object, the main difference is that the first one can change over time even without calling methods on it: adding and/or deleting record to the source schema can result in a change to Results object.
The only common thing between Results.indexOf and Array.indexOf is the name of the method.
Once said that is easy to also say that it makes no sense to compare the efficiency of the two methods.
In general, a problem common to all indexOf implementations is that they need a sequential scan and in the worst case (i.e. the not found case) a full scan is required. The wort implemented indexOf executed against 10 elements has no impact on program performances while the best implemented indexOf executed against 1M elements can have a severe impact on program performances. When possible it's always a good idea avoiding to use indexOf on large amounts of data.
Hope this helps.

Angular: How to map an array of 'mat-checkbox's to get strings associated with the checked checkboxes

To preface, I have found a solution that works for me in the situations I have tried it, but I am fairly new to javascript and RXJS and don't fully understand what the solution is doing so I can't be sure if it will work in every instance.
I am using reactive forms and have arrays of checkboxes, what I would like to do is get an array of all of the keys used to generate the checkboxes, but without any of the unchecked boxes. Ideally, I could use this to return additional values as well such as a user-readable string, but that is far from important as I can do that in a separate step fairly easily. I have come up with a few methods of my own, but they don't seem to be very robust or performant.
I would have replied on this thread, but I lack the reputation.
This is the best solution I have found, which I would be totally happy to use, but I don't have much experience with RXJS or maps in javascript so I am not totally sure what it is doing:
this.controlNames = Object.keys(this.checkboxGroup.controls).map(_=>_); //This seems to just produce an object of control keys as properties and their value
this.selectedNames = this.checkboxGroup.valueChanges.pipe(map(v => Object.keys(v).filter(k => v[k]))); //Some sort of magic happens and an array is generated and contains only the keys whose values are 'true'
I have tried breaking that snippet apart and using console.log to test what it is doing in each step, but it really didn't give me much useful information. Any advice or or better ideas would be thoroughly appreciated, there seem to be a lot of conventions in javascript that people adhere to and it can be hard to sort through what is a convention and what is actually doing something.
I think I found a way to break it down and get a grip on it and want to post my explanation for anyone who comes looking.
In this part, it is just creating an iterable map of the 'checkboxGroup.controls' object. This could have been used to loop over in the template and make all of the checkboxes. Since my form structure is already generated from arrays of objects with known properties, I don't need this. The underscores aren't doing anything special here, people just like to use them for private variables.
this.controlNames = Object.keys(this.checkboxGroup.controls).map(_=>_);
For those who are new to arrow functions or some of the conventions of javascript, the code above is not quite, but essentially shorthand for this:
this.controlNames = [];
Object.keys(this.checkboxGroup.controls).forEach(function(key) {
this.controlNames.push(key);
}
I have changed the short variables to longer ones to make them easier to understand in this second part. This maps the value changes observable as an iterable 'changesObj', retrieves the keys, and filters the keys by instances where the key has a true value. The code filter(key => changesObj[key]) returns the key if the key is not null, undefined, or false.
this.selectedNames = this.checkboxGroup.valueChanges.pipe(map(changesObj => Object.keys(changesObj).filter(key => changesObj[key])));
This is essentially just shorthand for this:
function propNotFalse (changes, prop) {
return changes[prop] == true;
}
this.selectedNames = this.alternateFilter = Object.keys(this.checkboxGroup.valueChanges).filter(this.propNotFalse.bind(null, this.checkboxGroup.valueChanges));

Should argument types be verified in JavaScript?

This should be simple question.
I have been using JavaScript for a couple years, and strongly typed languages (such as Java and C++) for even longer. I recall learning that, in the strongly typed languages, having to check types of arguments before doing stuff with them is symptom of bad code. However, does this carry over to languages like JavaScript?
/* in client-side JavaScript, for example, I find myself automatically doing stuff like this:
function myFunction(array1, array2)
{
if (array1 !== Array.from(array1)) return null;
if (array2 !== Array.from(array2)) return null;
// some array action here with arrays array1,array2
}
*/
Yes, before using it, you could take Array.isArray for checking if a variable is an array.
The Array.isArray() function determines whether the passed value is an Array.
The check for type is necessary if data comes from an unknown source, like to work with a alibrary, where the vendor does not know in advance what type of data the user supplies.
Some libraries uses a mixed mode for data where the data could be a single item or an array of items. In this case a check is necessary to determine if the item has to be wrapped in an array or not.
function myFunction(array1, array2) {
if (!Array.isArray(array1)) return null;
if (!Array.isArray(array2)) return null;
// some array action here with arrays array1,array2
}
The only place I have checked it was while writing the test cases.
I would say test case is the perfect example. We will be checking for both positive and negative scenarios. I hope you understand, if not let me know.

How do modern browsers implement JS Array, specifically adding elements?

By this I mean when calling .push() on an Array object and JavaScript increases the capacity (in number of elements) of the underlying "array". Also, if there is a good resource for finding this sort of information for JS, that would be helpful to include.
edit
It seems that the JS Array is like an object literal with special properties. However, I'm interested in a lower level of detail--how browsers implement this in their respective JS engines.
There cannot be any single correct answer to this qurstion. An array's mechanism for expanding is an internal implementation detail and can vary from one JS implementation to another. In fact, the Tamarin engine has two different implementations used internally for arrays depending on if it determines if the array is going to be sequential or sparse.
This answer is wrong. Please see #Samuel Neff's answer and the following resources:
http://news.qooxdoo.org/javascript-array-performance-oddities-characteristics
http://jsperf.com/array-popuplation-direction
Arrays in JavaScript don't have a capacity since they aren't real arrays. They're actually just object hashes with a length property and properties of "0", "1", "2", etc. When you do .push() on an array, it effectively does:
ary[ ary.length++ ] = the_new_element; // set via hash
Javascript does include a mechanism to declare the length of your array like:
var foo = new Array(3);
alert(foo.length); // alerts 3
But since arrays are dynamic in javascript there is no reason to do this, you don't have to manually allocate your arrays. The above example does not create a fixed length array, just initializes it with 3 undefined elements.
// Edit: I either misread your question or you changed it, sorry I don't think this is what you were asking.

Performance differences between jquery.inArray() vs Object.hasOwnProperty()?

I have a situation where I can choose to implement a collection of string keys as an object:
$.each(objects, function (key, object) {
collection[key] = "doesn't matter";
});
or an array:
$.each(objects, function (key, object) {
collection.push(key);
});
I'd like to be able to quickly determine whether or not the collection contains a given key. If collection is an object, I can use:
if (collection.hasOwnProperty(key_to_find)) { // found it!... }
else { // didn't find it... }
If collection is an array, I can use:
if ($.inArray(key_to_find, collection)) { // found it!... }
else { // didn't find it... }
I'd imagine using JavaScript's built-in hasOwnProperty would be faster than jQuery's inArray(), but I'm not entirely sure. Does anyone know more about the performance differences between these two methods? Or, is there a more efficient alternative here that I am not aware of?
If we're talking just how long it takes to check, then there's really no contest:
http://jsperf.com/array-vs-obj
hasOwnProperty is way way faster for the reasons stated by others.
Mmmh, if the collection is an array you can also use the native indexOf on it, no? https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
The array method is slower, because it requires linear time to find an element in the array (the code must step through potentially every element). hasOwnProperty will be much faster as it can use a hash table lookup, which occurs in constant time.
An object will have very fast access times for properties. However, you still have to account for overhead from calculating the hash etc (if the implementation uses hash tables to back objects). If the set of keys is relatively small, there shouldn't be too much of a difference. If it's larger, then I would go with the object/hash to store properties.
That said, it's a little easier to manage duplicate keys with the object, so I would personally would go with the dictionary.
Unless this is a bottleneck in your application, you shouldn't over think it.
Short Answer: .indexOf() (as #Claudio mentions)
Long Answer: Have a look at a quick speed test I coded up - http://jsfiddle.net/cvallance/4YdxJ/3/ - the difference is really negligible.

Categories

Resources