PDA

View Full Version : Scaling with map() function

jmrker
12-01-2012, 03:54 AM
I'm trying to understand the properties of the map() function.

So far I've figured how to do some simple actions.

<html>
<head>
<title>JavaScript Array MAP Methods</title>
<style type="text/css">
body { font-family:monospace; }
</style>
</head>
<body>
<script type="text/javascript">
// Ideas from: http://www.codingforums.com/showthread.php?t=276006

function createSequence(n) { return Object.keys(Object(Array(n)+"r")).map(Number); }
function sqr(n) { return n * n; }
function incrementSequence(n) { n = n + 1; return n; }
function limitPrecision(n) { return n.toFixed(3); }
function scaleFactor(n,sf) { return (n * sf); }

var numbers = [1, 4, 9, 16, 25, 36, 49];
var roots = numbers.map(Math.sqrt);
document.write('Sequence is: '+numbers+'<br>&nbsp;roots are : ' + roots );

numbers = createSequence(10);
var squares = numbers.map(sqr);
document.write('<p>Sequence is : '+numbers+"<br>squares are : " + squares );

var NUMBERS = numbers.map(incrementSequence);
document.write('<p>&nbsp;&nbsp;&nbsp;Sequence is : '+numbers+"<br>increments are : " + NUMBERS );

roots = NUMBERS.map(Math.sqrt);
document.write('<p>Sequence is: '+NUMBERS);
var Roots = roots.map(limitPrecision);
document.write('<br>&nbsp;roots are : ' + Roots.join(', ') );

</script>
</body>
</html>

So my question becomes, can I pass more than one parameter to the map()?
See the function below. While I get no syntax errors, it does not work when I try to scale each element in the array by a factor of 0.5

numbers = createSequence(10);
var scaled = numbers.map(scaleFactor,0.5);
document.write('<p>Sequence is : '+numbers+"<br>&nbsp;scaled are : " + scaled );

Is the secret to creating a scaled array to define another map() function passing only the scale factor?
Are multiple parameters not allowed in the map() function?

rnd me
12-01-2012, 11:19 AM
[].map accepts one extra argument, this :

[1,2,3,4,5].map(function scaleFactor(n, arrayIndex, wholeArray){ return n * this;}, 0.5)

jmrker
12-01-2012, 04:07 PM
[].map accepts one extra argument, this :

[1,2,3,4,5].map(function scaleFactor(n, arrayIndex, wholeArray){ return n * this;}, 0.5)

That works great.
In my effort to understand what it is doing and how it works,
I tried to make it a stand-alone function call like the others.

The following is my futile attempt. :confused:
Is there a way to call it like the highlighted in red line (commented out to make example work).

Also, if possible, could you expand on the explanation of how your function above works with the extra paramters that I don't see predefined?

<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<head>
<title>JavaScript Array MAP Methods</title>
<style type="text/css">
body { font-family:monospace; }
</style>
</head>
<body>
<div id="divArea"></div>

<script type="text/javascript">
// Ideas from: http://www.codingforums.com/showthread.php?t=276006

function createSequence(n) { return Object.keys(Object(Array(n)+"r")).map(Number); }
function sqr(n) { return n * n; }
function incrementSequence(n) { n = n + 1; return n; }
function limitPrecision(n) { return n.toFixed(3); }

var str = '';

var numbers = [1, 4, 9, 16, 25, 36, 49];
var roots = numbers.map(Math.sqrt);
str = 'Sequence is: '+numbers+'<br>&nbsp;roots are : ' + roots;
str += '<hr>';

numbers = createSequence(10);
var squares = numbers.map(sqr);
str += '<p>Sequence is : '+numbers+"<br>squares are : " + squares;
str += '<hr>';

var NUMBERS = numbers.map(incrementSequence);
str += '<p>&nbsp;&nbsp;&nbsp;Sequence is : '+numbers+"<br>increments are : " + NUMBERS;
str += '<hr>';

roots = NUMBERS.map(Math.sqrt);
str += '<p>Sequence is: '+NUMBERS;
var Roots = roots.map(limitPrecision);
str += '<br>&nbsp;roots are : ' + Roots.join(', ');
str += '<hr>';

/* */
// function scaleFactor(n, arrayIndex, wholeArray){ return n * this;};
numbers = createSequence(10);

// var scaled = numbers.map(scaleFactor),0.5} ; // THIS VERSION DOES NOT WORK

var scaled = numbers.map(function scaleFactor(n, arrayIndex, wholeArray){ return n * this;}, .5);
str += '<p>Sequence is&nbsp;: '+numbers+"<br>&nbsp;scaled are : " + scaled;

var tarr = numbers.map(incrementSequence);
scaled = tarr.map(function scaleFactor(n, arrayIndex, wholeArray){ return n * this;}, .5);
str += '<br>Sequence is : '+tarr+"<br>&nbsp;scaled are : " + scaled;
/* */
str += '<hr>';

document.getElementById('divArea').innerHTML = str;
</script>
</body>
</html>

rnd me
12-01-2012, 11:20 PM
That works great.
In my effort to understand what it is doing and how it works,
I tried to make it a stand-alone function call like the others.

The following is my futile attempt. :confused:
Is there a way to call it like the highlighted in red line (commented out to make example work).

Also, if possible, could you expand on the explanation of how your function above works with the extra paramters that I don't see predefined?

the red is a syntax error: unbalanced parens and a floating "}"...

if you want to "bake in" 0.5 so that it doesn't need passed, you can do so using bind:

function scaleFactor(n, arrayIndex, wholeArray){ return n * this;}
var scaleHalf=scaleFactor.bind(0.5);

[1,2,3,4,5].map(scaleHalf); // shows: [0.5, 1, 1.5, 2, 2.5]

the "extra" params are always defined for you by map/filter, i simply labeled them.

compare to a for-loop:

var r=[11,22,33,44,55], ob, i=0, mx=r.length;
for(i;i<mx;i++){
var ob=r[i];
out[i]=ob*0.5;
console.log(ob, i, r);
}
/*
//prints:
11 0 [11,22,33,44,55]
22 1 [11,22,33,44,55]
33 2 [11,22,33,44,55]
44 3 [11,22,33,44,55]
55 4 [11,22,33,44,55]
*/

map() is sightly simpler inho, and has scope, but the pattern is the same:

[11,22,33,44,55].map(function(ob, i, r){
console.log(ob, i, r);
return ob * 0.5;
});

/*
//prints:
11 0 [11,22,33,44,55]
22 1 [11,22,33,44,55]
33 2 [11,22,33,44,55]
44 3 [11,22,33,44,55]
55 4 [11,22,33,44,55]
*/

jmrker
12-01-2012, 11:54 PM
Thank you. :)

I'll go study on your explanation for awhile.