Krishna Chaitanya
Krishna Chaitanya

Reputation: 2663

JavaScript Array vs object/map when searching by value

I have some data for example student names. I added them to an object where key is the name and data is null.

I read on one of my own threads in stack overflow that objects perform better than arrays when searching by value. Because browsers use map algorithm/concept for objects. So I am using objects/maps extensively even if the data is not in key value pair format.

Is the usage of objects encouraged instead of an array even though the data is not in key value pair format?

Thank you.

Upvotes: 1

Views: 4371

Answers (2)

bvdb
bvdb

Reputation: 24760

I created a small benchmark just to be sure.

import { v1 as uuidv1 } from 'uuid';
import { sync_timer } from 'execution-time-decorators';

class Test {
  private createDataSet(size: number): Data[] {
    const arr: Data[] = [];
    for (let i = 0; i < size; i++) {
      const id = uuidv1();
      const value = uuidv1();
      arr.push({ id, value });
    }
    return arr;
  }

  private shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
  }

  runTest() {
    const dataSet = this.createDataSet(100000);

    // shuffle id's for lookup
    const ids = dataSet.map((d) => d.id);
    this.shuffleArray(ids);

    // prepare data in different formats.
    const map = new Map(dataSet.map((o) => [o.id, o]));
    const object = Object.assign({}, ...dataSet.map((o) => ({ [o.id]: o })));
    const sortedArr = [...dataSet];
    sortedArr.sort((a, b) => (a.id < b.id ? -1 : 1));

    this.testArray(dataSet, ids);
    this.testSortedArray(dataSet, ids);
    this.testMap(map, ids);
    this.testObject(object, ids);
  }

  @sync_timer
  private testArray(arr: Data[], ids: string[]) {
    return ids.map((id) => arr.find((o) => o.id === id));
  }

  @sync_timer
  private testSortedArray(arr: { id }[], ids: string[]) {
    return ids.map((id) => arr[sortedIndexBy(arr, { id }, (o) => o.id)]);
  }

  @sync_timer
  private testMap(map: Map<string, Data>, ids: string[]) {
    return ids.map((id) => map.get(id));
  }

  @sync_timer
  private testObject(object: any, ids: string[]) {
    return ids.map((id) => object[id]);
  }
}

The output of this test is:

[timer] [Test::testArray]: begin
[timer] [Test::testArray]: timer 18.636s
[timer] [Test::testSortedArray]: begin
[timer] [Test::testSortedArray]: timer 0.115s
[timer] [Test::testMap]: begin
[timer] [Test::testMap]: timer 0.016s
[timer] [Test::testObject]: begin
[timer] [Test::testObject]: timer 0.015s

Of course there are a number of different factors that can influence the result. In general the difference between using a Map or an object is neglectable.

If anything, it's useful to know that a Map isn't faster. It just has some other features. (e.g. they support keys that aren't strings).

The find function of an array is only an option for small arrays. Even matching all keys in an array of just 4000 elements, is likely to cost you more than 5 seconds.

You could get tempted to try a home-made binary search on a sorted array to speed things up, however that would be a waste of time. As you can see, the lookup of a Map (or on object keys) outperforms a simple binary search.

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074585

Is the usage of objects encouraged instead of an array even though the data is not in key value pair format?

That's a purely subjective question, so let's rephrase it:

Is using objects to track unique values (using the value as a key) faster than using arrays to track unique values (using the value as an entry)?

Almost certainly, yes, although of course if performance is a concern you should check it on your target JavaScript engines, with a representative sample of your target data, as both the engine and the data set may affect the result.

It also depends on how you use the object:

The common practice of putting a prefix on the keys to avoid conflicts with things to "toString" that the object gets from Object.prototype can, for instance, impact or even negate the performance advantage (but there are better ways, particularly with ES5). Note that ES6 will provide Map and Set objects, which don't have the issue with toString and such.

But for instance, here's a test on jsPerf that checks for 10 values that do exist and 10 that don't in an array with 100 entries or an object with 100 properties; the various object versions wins easily on Chrome (V8), Firefox (SpiderMonkey), and IE11 (JScript) with the exception of the one that uses string concatenation:

enter image description here

(Operations per second, higher is better.)

Setup:

var arr = [
    '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'
];

// The object equivalent for testing for uniqueness
var obj = arr.reduce(function(o, key) {
    o[key] = true;
    return o;
}, {});

// The same, with using an object with no prototype so
// we don't need to worry about `"toString"` and such
var nullObj = arr.reduce(function(o, key) {
    o[key] = true;
    return o;
}, Object.create(null));

// The same, using a prefix on the values to avoid the
// issue with `"toString"` (common pre-ES5)
var prefixedObj = arr.reduce(function(o, key) {
    o[" " + key] = true;
    return o;
}, {});

// Not in the object or array
var negatives = [
    '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'
];

// A list of random choices from the array to check for, both ones we'll find and ones we won't
var choices = (function() {
    var n = 0, rv = [], index = 0;
    while (rv.length < 40) {
        n += Math.floor(Math.random() * 5);
        rv.push(arr[n]);
        if (index < negatives.length) {
            rv.push(negatives[index++]);
        }
    }
    return rv;
})();

Test Array#indexOf(value):

var found = choices.reduce(function(acc, value) {
    if (arr.indexOf(value) !== -1) {
        ++acc;
    }
    return acc;
}, 0);
if (found !== 20) { throw "Error in test"; }

Test obj.hasOwnProperty(value):

var found = choices.reduce(function(acc, value) {
    if (obj.hasOwnProperty(value)) {
        ++acc;
    }
    return acc;
}, 0);
if (found !== 20) { throw "Error in test"; }

Test obj[value]:

// Warning: To use this way of checking, you need to be sure your
// values don't happen to match something from Object.prototype,
// such as `toString` or `valueOf`
var found = choices.reduce(function(acc, value) {
    if (obj[value]) {
        ++acc;
    }
    return acc;
}, 0);
if (found !== 20) { throw "Error in test"; }

Test nullObj[value]:

// Note the object was created with no prototype (Object.create(null))
var found = choices.reduce(function(acc, value) {
    if (nullObj[value]) {
        ++acc;
    }
    return acc;
}, 0);
if (found !== 20) { throw "Error in test"; }

Test prefixedObj[value]:

// The string concat is hard on performance
var found = choices.reduce(function(acc, value) {
    if (prefixedObj[" " + value]) {
        ++acc;
    }
    return acc;
}, 0);
if (found !== 20) { throw "Error in test"; }

Upvotes: 5

Related Questions