Performance: findIndex vs Array.prototype.map [duplicate]

走远了吗. 提交于 2020-01-04 07:32:06

问题


In 2019, if I am handling an array of objects, with a length north of say 15000 and I need to find an index of an object by value, which of the following methods is going to be my best option performance-wise?

Six year old 'answer': In an array of objects, fastest way to find the index of an object whose attributes match a search

findIndex

array.findIndex(object => foo === object.id);

Array.prototype.map

array.map(object => object.id).indexOf(foo);

回答1:


Conceptually, these two snippets accomplish the same goal, but they go about it very different ways. To understand how the two solutions are different, let's first look at findIndex:

The findIndex method executes the callback function once for every array index 0..length-1 (inclusive) in the array until it finds one where callback returns a truthy value.
emphasis mine

In other words, it will stop as soon as it finds the item you're looking for. indexOf has a similar behavior, because it will return the index of the first item found.

On the other hand, looking at map:

map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results.
emphasis mine

In other words, map doesn't care what item you're search for. Even if the item you're looking for is the first item in the array, map will still loop through 14999 other items to create a new array of id's. This means you'll end up doing quite a lot more work to achieve the same results, both in terms of temporal complexity (more time needed to loop through all those items) and spatial complexity (more memory needed to store that temporary array).

Side note: The above is not necessarily true if you use iterators / generators, which can sort of 'look ahead' in a sense to see if more work is needed. But I think this is outside the scope of this question.

However, if you're really concerned about performance, it's always a good idea to run a test for yourself. Here's a quick benchmark to demonstrate the relative performance of the two implementations. On my machine, I get findIndex: 0.023ms / map+indexOf: 0.572ms. Your mileage may vary somewhat:

var suite = new Benchmark.Suite();

const haystack = [];
let needle;

suite
  .add('findIndex', () => haystack.findIndex(o => o.id === needle))
  .add('map+indexOf', () => haystack.map(o => o.id).indexOf(needle))
  .on('start', () => {
    for (let i = 0; i < 15000; i++) {
      haystack.push({
        id: Math.random().toString(36).substring(7)
      });
    }
    console.log('Starting test.');
  })
  .on('cycle', () => {
    needle = haystack[Math.floor(Math.random() * haystack.length)].id;
  })
  .on('complete', () => {
    console.log('Test results (lower is better):')
    suite.forEach((bench) => {
      console.log(`  ${bench.name}: ${(bench.stats.mean * 1000).toFixed(3)}ms`);
    });
  })
  .run({
    'async': true
  });
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.min.js"></script>


来源:https://stackoverflow.com/questions/55246694/performance-findindex-vs-array-prototype-map

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!