How to implement Javascript ECMA 5 array.map () for a sparse array?

It should be quite simple to implement array.map() defined in ECMA-262 , which takes a function, and this function will be called in 3 arguments: element value, index, array.

But what about a sparse array? Obviously, we do not want to iterate from index 0 to 100,000, if only index 0, 1, 2 and 100 000 have an element, and otherwise, with index 3 to 99,999. I can think of using arr.slice(0) or arr.concat() to clone an array and then enter replaced values, but what if we don't use slice or concat , is there any other way to do this?

The solution I used with slice() is:

 Array.prototype.collect = Array.prototype.collect || function(fn) { var result = this.slice(0); for (var i in this) { if (this.hasOwnProperty(i)) result[i] = fn(this[i], i, this); // 3 arguments according to ECMA specs } return result; }; 

( collect used to check the code, as this is another name for map in some language)

+4
source share
2 answers

It should be easy, but there are a few special points.

The callback function allows you to modify the array in question. Any items that it adds or removes are not visited. Therefore, it seems to us that we should use something like Object.keys to determine which elements should be visited.

In addition, the result is defined as a new array, "created as if" by an array constructor occupying the length of the old array, so we could also use this constructor to create it.

Here the implementation takes these things into account, but some other subtleties are probably missing:

 function map(callbackfn, thisArg) { var keys = Object.keys(this), result = new Array(this.length); keys.forEach(function(key) { if (key >= 0 && this.hasOwnProperty(key)) { result[key] = callbackfn.call(thisArg, this[key], key, this); } }, this); return result; } 

I assume that Object.keys returns the keys of the array in numerical order, which, in my opinion, is determined by the implementation. If it is not, you can sort them.

+2
source

You do not need to use this.slice(0) . You can simply make the result array and assign values ​​to any index:

 Array.prototype.collect = Array.prototype.collect || function(fn) { var result = []; for(var i in this) { if (this.hasOwnProperty(i)) { result[i] = fn(this[i]); } } return result; } 
0
source

Source: https://habr.com/ru/post/1438792/


All Articles