0
\$\begingroup\$

I want to check whether or not an object exists in an array given its key (key is not unique).

The object takes the form:

class item {
    key: string,
    value: (string|int|boolean),
    id: Guid
}

And this._items is an item array.

First approach is simply filtering the array and checking its length:

has(key) {
    return this._items.filter(item => item.key === key).length > 0;
}

Then a for loop that terminates when exists is true.

has(key) {
    let exists = false;
    for (let i = 0; i < this._items.length && !exists; i++) {
        exists = this._items[i].key === key;
    }

    return exists;
}

One more take on it, this.keys() returns an array of unique item keys:

has(key) {
    return this.keys().toString().match(new RegExp(key, 'ig')).length > 0;
}

The first one is cleaner / more readable but iterates over every item in the array. The second one doesn't read quite as well but only iterates over as many items as it needs to.

Until it needs to be optimized, is this just a preference/coding-style thing?

\$\endgroup\$
  • \$\begingroup\$ Instead of filter, use find \$\endgroup\$ – Tushar Oct 26 '16 at 2:50
  • 2
    \$\begingroup\$ Use ES5 some() or return/break from the loop. \$\endgroup\$ – wOxxOm Oct 26 '16 at 2:51
2
\$\begingroup\$

Easy to clean up your second suggestion, at which point, I would prefer it.

has(key) {
    for (let i = 0, len = this._items.length; i < len; i++) {
        if (key in this._items[i]) return true;        
    }
    return false;
}

Note I determinethis._items.length only once with this approach vs. on every iteration.

You may consider returning index position of found item (or found item itself) here to make this more useful, because presumably you are checking for this key because you want to access it somehow. The caller would need to be aware of potential falsey behavior of 0 vs. false or similar. You also would probably want to rename the function at this point to something more meaningful like getIndexHavingKey() or getItemHavingKey()

Of course, this is essentially what Array.find() and Array.findIndex() do. You would just need to implement your key check check in callback. That might look something like this:

var search = { key: 'someKey' };
// define filter callback
var keyExistsFilter = function (element) {
    // here 'this' is search object passed via find or findIndex
    return (this.key in element);
}

// get item from array based on filter
var itemWithKey = this._items.find(keyExistsFilter, search);

// get item index from array based on filter
var itemIndexWithKey = this._items.findIndex(keyExistsFilter, search);
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.