Reputation: 361
Write a function capitals that takes a single string (word) as argument. The functions must return an ordered list containing the indexes of all capital letters in the string.
Example
Test.assertSimilar( capitals('CodEWaRs'), [0,3,4,6] );
My solution is this which is the simple for loop:
function capitals(word) {
var ara = [];
for(var i = 0; i < word.length; i++){
if(word[i] == word[i].toUpperCase()){
ara.push(i)
}
}
return ara;
}
But I want to understand this one using higher order function:
function capitals(word) {
return word.split('').map(function(item, i) {
return item == item.toUpperCase() ? i : null;
}).filter(function(x) {
return x != null;
});
}
especially the 'map(function(item, i)' part say why it knows i is the index without us defining it anywhere?
Thanks for your help!
Upvotes: 2
Views: 529
Reputation: 35950
See code comments:
function capitals(word) {
return word
.split('') // split a word in an array of letters
.map(function(item, i) {
// if letter is an upper case, return its index, null otherwise
return item == item.toUpperCase() ? i : null;
}).filter(function(x) {
// filter out all null elements, effectively leaving only
// indices of uppercase letters in a string.
return x != null;
});
}
For an explanation of map(), see this MDN page. The function passed to map()
is a callback which is taking three arguments - the element from an array over which map() is called, an index of this element in the array and an array itself.
Here's an example of map()
itself. Consider this code:
var result = ['a', 'b', 'c', 'd'].map(function(element, index) {
console.log('element ' + element + ' is at position: ' + index);
return index % 2 === 0 ? element.toUpperCase() : element;
});
console.log(result);
It will print:
element a is at position: 0
element b is at position: 1
element c is at position: 2
element d is at position: 3
['A', 'b', 'C', 'd']
Note that in this example we're using index parameter to capitalize only every other letter. Also note that map()
would work with array of numbers, objects etc, not only letters.
Upvotes: 2
Reputation: 149010
why it knows i is the index without us defining it anywhere?
It actually is defined, within the map
function. For every item in the source array, it will provide three parameters to the callback
function that you pass in. From MDN:
callback
Function that produces an element of the new Array, taking three arguments:
currentValue
The current element being processed in array.index
The index of the current element being processed in array.array
The array map was called upon.
Upvotes: 1
Reputation: 15773
map
applies a function to each element of the collection, in your case after split
you have an array of chars, item
is the current char and i
is the index, the first operation:
return item == item.toUpperCase() ? i : null;
Is applied to all chars and reads, if this char is upper case return the index, else return null
(this syntax condition ? value : default
is called ternary operator).
The second is a filter to remove the null values from the array leaving only the indexes.
Upvotes: 1
Reputation: 6051
That's the beauty of map
: you don't have to write your for
loop, it's already in the body of the map
function.
The body of map
contains a for loop which declares the index and "injects" it into the function you passed to it.
Upvotes: 1