swordlordswamplord
swordlordswamplord

Reputation: 430

Creating my own array.prototype.map method. How can I access the array?

So I am trying to create a method that mimic exactly what the Array.prototype.map() method does and there is a lot I am confused about. The main problem I suppose comes down to its syntax. I know there are many different ways to utilitize the map method for instance:

example 1:

let say I have an array of objects -

var movieList = [
   {"Title" : "Inception",
   "Awards" : "4 oscars",
   "Language" : "English",
   "imdbRating" : "8.8"
   },

   {"Title" : "Inception2",
   "Awards" : "44 oscars",
   "Language" : "English and Spanish",
   "imdbRating" : "9.8"
   },

   {"Title" : "Interstellar",
   "Awards" : "10 oscars",
   "Language" : "English",
   "imdbRating" : "9.5"
   }
];

Lets say I want to make a function that returns a list of objects that contains only the title of the movie and its imdbRating. In this case, I can use the map() method:

let newList = movieList.map( (current) ({'title': current['Title'],     
               'rating': current['imdbRating'] }) );

the above line of code satisfies what i need to achieve my objective using the map method. However, the syntax can be different for other cases

example 2:

let s = [1, 2, 3, 4];

let s2 = s.map( function(item) {
   return item*2;
});

using the map function s2 will return an array that has for each element double the value of each element in the s array. Now, going back to the theme of this post, the problem I am working on gave me this outline to start with:

Array.prototype.myMap = function(callback) {
   let newArray = [];

I understand that when an array calls on the myMap method, it is inserting 2 arguments, the array and a function. But I cannot wrap my head around how I can concretely assign the value of each callback function on the element to the newArray in the myMap method. Especially because I do not know how to access the original array.

One of my attempts that I know is ridiculous because I do not know how I can access the length of the array as well as the array itself which calls on the myMap method-

Array.prototype.myMap = function(callback) {
   let newArray = [];
   let x = this.length();
   for(let i=0; i<x; i++){
       let counter = callback();
       newArray.push(counter);
   }
   return newArray;
};

the way I've understood the map() method thus far, is it takes 3 arguments, an array, a function, and the element that will be put thru the function and I do not know the syntax well enough to iterate over the array that calls on the map method and nowhere in my course have I been taught how to do this and I have not found any online resource either that offers a solution to this problem.

Upvotes: 5

Views: 11439

Answers (10)

agnid&#233;
agnid&#233;

Reputation: 335

my proposition on how to doing with recursive way with typescript

Array.prototype.customMap = function customMap<T>(
  callback: (element: T, index: number, array: T[], self?: T[]) => T
): T[] {
  if (this.length === 0) {
    return [];
  }
  return (([index, result]) => {
    return [
      callback(
        this[this.length - 1 - index],
        this.length - 1 - index,
        this,
        this
      ),
      ...result,
    ];
  })(mapWithSize<T>(this.slice(1), callback));
};


function mapWithSize<T>(
  sequence: T[],
  callback: (element: T, index: number, array: T[], self?: T[]) => T
): [number, T[]] {
  return [sequence.length, sequence.customMap(callback)];
}

Upvotes: 0

Apurv
Apurv

Reputation: 113

Creating a custom map function in javascript

 Array.prototype.myMap = function (cb){
    let temp =[];
    for(let i = 0; i < this.length; i++){
    temp.push(cb(this[i], i, this))
    }
    return temp;
    };

In this custom function callback cb having three arguments is current element, index and actual array.

const arr = [1, 2, 3, 4];
//using myMap
arr.myMap((num)=>num)

Upvotes: 0

phtn458
phtn458

Reputation: 505

You can also use forEach if you don't want to use a for loop

Array.prototype.myMap = function (callback) {
  let newArr = [];
  this.forEach((item) => {
    let elem = callback(item);
    newArr.push(elem);
  });
  return newArr;
};

Upvotes: 0

Manos Kaparos
Manos Kaparos

Reputation: 139

Like this answer, but correctly preserves empty items.

Array.prototype.map = function (callback, thisArg) { 
    let arr = [];
    const len = this.length;
    for (let i = 0; i < len; i++) {
        if (i in this) arr.push(callback.call(thisArg, this[i], i, this));
        else arr.length++;
    }
    return arr;
};

Upvotes: 1

iMagic
iMagic

Reputation: 21

You could take advantage of the spread operator and do something like this:

Map.prototype.slice = function(start, end) {
    return new Map([...this].slice(start, end));
};

And in use:

const testMap = new Map([["a", 1], ['b', 2], ["c", 3], ["d", 4], ["e", 5]]);
console.log(testMap); // Map(5) { 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }
console.log(testMap.slice(0, 2)); // Map(2) { 'a' => 1, 'b' => 2 }

You can definitely build upon this since this still has the caveats of Array.prototype.slice().

Upvotes: 0

Dendi 4890
Dendi 4890

Reputation: 31

Array.prototype.mappy = function (callback, thisArg) { 
    let newArray = [];
    for (let i = 0; i < this.length; i++) {
        if (i in this) newArray.push(callback.call(thisArg, this[i], i, this));
        else newArray.push(undefined);
    }
    return newArray;
};

Upvotes: 0

Benjamin Davies
Benjamin Davies

Reputation: 353

Here is a working version of your myMap function.

A part of imitating these methods that may confuse people is how the this keyword works in javascript. Here is an MDN Reference article.

Array.prototype.myMap = function(callback, thisArg) {
  let newArray = [];
  let x = this.length;
  for(let i=0; i<x; i++){
    let counter = callback.call(thisArg, this[i], i, this);
    newArray.push(counter);
  }
  return newArray;
};

Upvotes: 0

adiga
adiga

Reputation: 35222

This is simplified version of the actual map Polyfill. You need to get the length using this.length. And pass the current item in loop, it's index, and the array itself as a parameter to callback

Array.prototype.myMap = function(callback, thisArg) {
  const newArray = [];
  const length = this.length;

  for (let i = 0; i < length; i++) {
    let value = callback(this[i], i, this); // call with proper arguments
    newArray.push(value);
  }

  return newArray;
};

const arr = [1, 2, 3];

console.log(arr.myMap(a => a * 2))

Note: map method also takes a thisArg as parameter. If you want to use that, you need to call the callback with thisArg as this

callback.call(thisArg, this[i], i, this);

Upvotes: 4

Tahlil
Tahlil

Reputation: 1091

Here is where you can learn about javascript map function more: https://www.w3schools.com/jsref/jsref_map.asp

Implementing map method is actually quite easier than you think. Here is a really simple example that would do exactly what the map method do from https://www.w3schools.com/jsref/jsref_map.asp:

Array.prototype.myMap = function(callback) {
    arr = [];
    for (var i = 0; i < this.length; i++)
        arr.push(callback(this[i], i, this));
    return arr;
};

//tests
var numbers2 = [1, 4, 9];

var squareRoot = numbers2.myMap(function(num) {
    return Math.sqrt(num);
});

console.log(squareRoot); // [ 1, 2, 3 ]

So, the map method simply returns an array by whose values map to the original array's values by running a specified function given as an argument on each of the values.

Note: The method skips the optional parameter of the original map function which specifies what will be the this value

Upvotes: 0

Jack Bashford
Jack Bashford

Reputation: 44105

length is not a method - it's just a property. And you need to pass this[i] to the callback for the correct output.

Array.prototype.myMap = function(callback) {
  let newArray = [];
  let x = this.length;
  for (let i = 0; i < x; i++) {
    let counter = callback(this[i]);
    newArray.push(counter);
  }
  return newArray;
};

let arr = [1, 2, 3];
arr = arr.myMap(e => e * 2);
console.log(arr);

Please note it's quite bad practice to mutate the prototype methods - and especially creating a new one when an identical method exists. (map has all the functionality of myMap plus more).

Upvotes: 8

Related Questions