JonathanMitchell
JonathanMitchell

Reputation: 400

rewriting Map with forEach

The forEach method does not return a new string with the result of the values. If I want to rewrite the map method using forEach, I cannot use the command push.forEach(array,callback).

I am attempting to use the forEach method to multiply each element in my array by 2 and store it in a new array. I do not want advice on using the map method because I know it already does this.

Without using the forEach method my code is as follows:

function MultiplyByTwo(num) {
    return num * 2;
}

function HostMultiplyByTwo(array,instructions) {
    var output = [];
    for (i=0;i<array.length;i++) {
        output.push(instructions(array[i]))
    }
    return output;
}

var endresult = HostMultiplyByTwo([1,2,3],MultiplyByTwo)

If the forEach function looks like this:

function forEach(array, callback) {
    for (var i =0;i<array.length;i++) {
        var result = callback(array[i])
    }
    return result;
}

Now I would like to be able to run HostMutiplyByTwo using the forEach method. Here is what I tried.

function HostMultiplyByTwo(array,instructions) {
    var output = [];
    forEach(array,instructions) {
        output.push(result)
    }
    return output;
}

var endresult = HostMultiplyByTwo([1,2,3],MultiplyByTwo)

This clearly does not work for some reason. I understand that the forEach method simply iterates through the first parameter and performs the function in its second parameter on the first parameter.

Any help is much appreciated.

Upvotes: 1

Views: 1150

Answers (2)

Daniel
Daniel

Reputation: 1087

What do you think this is supposed to do?

forEach(array,instructions) {
    output.push(result)
}

forEach is just a method - it isn't a construct like if. If you use your function syntax (and not the built in method), You'll need to do something like

forEach(array, function (element) {
    output.push(instructions(element))
});

Notice the anonymous function wraps pushing the result of the function onto output - you get this for free from map.

You can avoid the anonymous function by using a named closure

var pusher = function (element) {
    output.push(instructions(element))
};

forEach(array, pusher);

You can even build the closure dynamically

var pusherCreator = function (outputArray, callback) {
    var pusher = function(element) {
        outputArray.push(callback(element));
    };

    return pusher;
};

forEach(array, pusherCreator(output, instructions));

Upvotes: 4

RobG
RobG

Reputation: 147403

Within the forEach function you have:

for (var i =0;i<array.length;i++) {
  var result = callback(array[i])
}

which just assigns a new value to result on each iteration. You need to assign the value to an array, so:

var result = [];
for (var i =0;i<array.length;i++) {
  result.push(callback(array[i]));
}

Now in the HostMultiplyByTwo function, you just need:

var output = forEach(array,instructions)
return output;

or just:

return forEach(array,instructions);

Note that by convention, variable names starting with a capital letter are reserved for constructors. Variables with all capitals are for constants.

So the whole thing looks like:

function multiplyByTwo(num) {
    return num * 2;
}

function forEach(array, callback) {
  var result = [];
  for (var i=0; i<array.length; i++) {
    result.push(callback(array[i]));
  }
  return result;
}

function hostMultiplyByTwo(array,instructions) {
    return forEach(array,instructions)
}

document.write(hostMultiplyByTwo([1,2,3], multiplyByTwo));

Note that if you want to deal with sparse arrays and properly replicate map and forEach (which only visit members that exist), you need to test if each i member of the source array exists, so forEach becomes:

  for (var i=0; i<array.length; i++) {
    if (array.hasOwnProperty(i)) {
      result[i] = callback(array[i]);
    }
  }

So that non–existent members remain non–existent.

Upvotes: -1

Related Questions