book

Lodash Drills

Complete the following Lodash exercises. The goal is to become really good at functional programming paradigm (e.g., _.map, _.filter, _.all, _.any ...etc) and a number of really useful Lodash methods (e.g., _.find, _.pluck ... etc).

  • enter your solution in the solution block
  • utilize lodash functions as much as possible
  • no for/while loop is allowed

Familiarity with programming in this way will not only make you a super productive programmer but also will pave the way for you to learn MapReduce and MongoDB.

Examples

How many people?

Done
Data
[{name: 'John'}, {name: 'Mary'}, {name: 'Joe'}, {name: 'Ben'}]
Expected Output
4
Actual Output
4
Solution
// Here we just need to count the number of elements in the data araay
return data.length

What are the names?

Done
Data
[{name: 'John'}, {name: 'Mary'}, {name: 'Joe'}, {name: 'Ben'}]
Expected Output
[
  "John",
  "Mary",
  "Joe",
  "Ben"
]
Actual Output
[
  "John",
  "Mary",
  "Joe",
  "Ben"
]
Solution
// Here we operate on every element of the data array (so no filter is
// necessary) and we return the property value of the name: field
// NOTE - _.map returns an array of values for each element in Collection while
//        _.filter returns an array of all elements for which predicate is true

return _.map(data, function(d) {
    return d.name
})

Exercises

What names begin with the letter J?

Done
Data
[{name: 'John'}, {name: 'Mary'}, {name: 'Joe'}, {name: 'Ben'}]
Expected Output
[
  "John",
  "Joe"
]
Actual Output
[
  "John",
  "Joe"
]
Solution
// Here we filter based on if the property value of name: field starts with the letter 'J'
// Since filter returns the data array element that for which the test is true we
// pluck out the resulting value of the name: field from each returned array element

return _.pluck(_.filter(data, function(d) {
    return _.startsWith(d.name, 'J')
}), 'name')

How many Johns?

Done
Data
[{name: 'John'}, {name: 'John'}, {name: 'John'}, {name: 'Ben'}]
Expected Output
3
Actual Output
3
Solution
// Here we use filter with the shorthand _.matches notation to pick out which name: fields
// are of the property value 'John' and use _.size to count number of returned array elements

return _.size(_.filter(data, _.matches({'name': 'John'})))

What are all the first names?

Done
Data
[{name: 'John Smith'}, {name: 'Mary Kay'}, {name: 'Peter Pan'}, {name: 'Ben Franklin'}]
Expected Output
[
  "John",
  "Mary",
  "Peter",
  "Ben"
]
Actual Output
[
  "John",
  "Mary",
  "Peter",
  "Ben"
]
Solution
// Here we use map since operating on every data array element with a nested
// splitting of the name: property value, returning the first string (first name) of value

return _.map(data, function(d) {
    return _.first(d.name.split(' '))
})

What are the first names of Smith?

Done
Data
[{name: 'John Smith'}, {name: 'Mary Smith'}, {name: 'Peter Pan'}, {name: 'Ben Smith'}]
Expected Output
[
  "John",
  "Mary",
  "Ben"
]
Actual Output
[
  "John",
  "Mary",
  "Ben"
]
Solution
// Here we first filter the data to determine which array elements include
// the string 'Smith', then we used the filtered array result as an input
// to _.map which iterates over and pulls out (_.splits) the first name of 
// returned filtered array.  FIXME: This most likely can be improved

var f_data = _.filter(data, function(d) {
    if (_.includes(d.name, "Smith")) {
        return 1
    }
})
return _.map(f_data, function(f) {
    return _.first(f.name.split(' '))
})

Change the format to lastname, firstname

Done
Data
[{name: 'John Smith'}, {name: 'Mary Kay'}, {name: 'Peter Pan'}]
Expected Output
[
  {
    "name": "Smith, John"
  },
  {
    "name": "Kay, Mary"
  },
  {
    "name": "Pan, Peter"
  }
]
Actual Output
[
  {
    "name": "Smith, John"
  },
  {
    "name": "Kay, Mary"
  },
  {
    "name": "Pan, Peter"
  }
]
Solution
return _.map(data, function(d) {
    return {'name': _.last(d.name.split(' ')) + ', ' + _.first(d.name.split(' '))}
})

How many women?

Done
Data
[{name: 'John Smith', gender: 'm'}, {name: 'Mary Smith', gender: 'f'}, {name: 'Peter Pan', gender: 'm'}, {name: 'Ben Smith', gender: 'm'}]
Expected Output
1
Actual Output
1
Solution
// Here we use the _.filter shorthand _.matches notation to find all data
// array elements that have the gender: value of 'f' and count with _.size

return _.size(_.filter(data, {gender: 'f'}))

How many men whose last name is Smith?

Done
Data
[{name: 'John Smith', gender: 'm'}, {name: 'Mary Smith', gender: 'f'}, {name: 'Peter Pan', gender: 'm'}, {name: 'Ben Smith', gender: 'm'}]
Expected Output
2
Actual Output
2
Solution
// Filter to find males (gender: 'm'); Filter to find names: that include Smith
// _map to iterate result and find last names of 'Smith'

var males = _.filter(data, {gender: 'm'})
var names = _.filter(males, function(d) {
    if(_.includes(d.name, "Smith")) {return 1}
})
return _.size(_.map(names, function(f) {
    return _.last(f.name.split(' '))
}))

Are there more men than women?

Done
Data
[{name: 'John Smith', gender: 'm'}, {name: 'Mary Smith', gender: 'f'}, {name: 'Peter Pan', gender: 'm'}, {name: 'Ben Smith', gender: 'm'}]
Expected Output
true
Actual Output
true
Solution
var result = false
if (_.size(_.filter(data, {gender: 'm'})) > _.size(_.filter(data, {gender: 'f'}))) {result = true}
return result

What is Peter Pan's gender?

Done
Data
[{name: 'John Smith', gender: 'm'}, {name: 'Mary Smith', gender: 'f'}, {name: 'Peter Pan', gender: 'm'}, {name: 'Ben Smith', gender: 'm'}]
Expected Output
"m"
Actual Output
"m"
Solution
// Filter input data array to find {name: 'Peter Pan'}, then _.pluck to get 'gender' field
// Since _.pluck returns array, then use _.first to get first element of the array

return _.first(_.pluck(_.filter(data, {name: 'Peter Pan'}), 'gender'))

What is the oldest age?

Done
Data
[{name: 'John Smith', age: 54}, {name: 'Mary Smith', age: 42}, {name: 'Peter Pan', age: 15}, {name: 'Ben Smith', age: 35}]
Expected Output
54
Actual Output
54
Solution
// _.pluck to look at all 'age' fields and then get _.max

return _.max(_.pluck(data, 'age'))

Is it true everyone is younger than 60?

Done
Data
[{name: 'John Smith', age: 54}, {name: 'Mary Smith', age: 42}, {name: 'Peter Pan', age: 15}, {name: 'Ben Smith', age: 35}]
Expected Output
true
Actual Output
true
Solution
// use _.all

return _.all(data, function(n) {
    return n.age < 60
})

Is it true someone is not an adult (younger than 18)?

Done
Data
[{name: 'John Smith', age: 54}, {name: 'Mary Smith', age: 42}, {name: 'Peter Pan', age: 15}, {name: 'Ben Smith', age: 35}]
Expected Output
true
Actual Output
true
Solution
// use _.some

return _.some(data, function(n) {
    return n.age < 18
})

How many people whose favorites include food?

Done
Data
[{name: 'John Smith', age: 54, favorites: ['food', 'movies']},
 {name: 'Mary Smith', age: 42, favorites: ['food', 'travel']},
 {name: 'Peter Pan', age: 15, favorites: ['minecraft', 'pokemo']},
 {name: 'Ben Smith', age: 35, favorites: ['craft', 'food']}]
Expected Output
3
Actual Output
3
Solution
// Need to process all entries to determine for each entry if (_.filter) 'food' is an
// element of favorites sub-array and count

return _.size(_.filter(data, function(n) {
    return _.some(n.favorites, function (d) {
        return d == 'food'
    })
}))

Who are over 40 and love travel?

Done
Data
[{name: 'John Smith', age: 54, favorites: ['food', 'movies']},
 {name: 'Mary Smith', age: 42, favorites: ['food', 'travel']},
 {name: 'Peter Pan', age: 15, favorites: ['minecraft', 'pokemo']},
 {name: 'Joe Johnson', age: 46, favorites: ['travel', 'movies']},
 {name: 'Ben Smith', age: 35, favorites: ['craft', 'food']}]
Expected Output
[
  "Mary Smith",
  "Joe Johnson"
]
Actual Output
[
  "Mary Smith",
  "Joe Johnson"
]
Solution
return _.pluck(_.filter(data, function(n) {
    return _.some(n.favorites, function(d) {
        return d == 'travel'
    })
    return n.age > 40
}), 'name')

Who is the oldest person loving food?

Done
Data
[{name: 'John Smith', age: 54, favorites: ['food', 'movies']},
 {name: 'Mary Smith', age: 42, favorites: ['food', 'travel']},
 {name: 'Peter Pan', age: 15, favorites: ['minecraft', 'pokemo']},
 {name: 'Joe Johnson', age: 46, favorites: ['travel', 'movies']},
 {name: 'Ben Smith', age: 35, favorites: ['craft', 'food']}]
Expected Output
"John Smith"
Actual Output
"John Smith"
Solution
// FIXME: I don't understand why I can't simply _.pluck out the name: value 
// from the _.filter/_.some nested loop

var m_data =  _.max(_.filter(data, function(f) {
    return _.some(f.favorites, function(d) {
        return d == 'food'
    })
}), 'age')
return m_data.name

What are all the unique favorites?

Done
Data
[{name: 'John Smith', age: 54, favorites: ['food', 'movies']},
 {name: 'Mary Smith', age: 42, favorites: ['food', 'travel']},
 {name: 'Peter Pan', age: 15, favorites: ['minecraft', 'pokemo']},
 {name: 'Joe Johnson', age: 46, favorites: ['travel', 'movies']},
 {name: 'Ben Smith', age: 35, favorites: ['craft', 'food']}]
Expected Output
[
  "food",
  "movies",
  "travel",
  "minecraft",
  "pokemo",
  "craft"
]
Actual Output
[
  "food",
  "movies",
  "travel",
  "minecraft",
  "pokemo",
  "craft"
]
Solution
// hint: use _.pluck, _.uniq, _.flatten in some order
// Didn't need _.pluck in this exercise...

return _.uniq(_.flatten(_.map(data, function(d) {
     return d.favorites
})))

What are all the unique last names?

Done
Data
[{name: 'John Smith', age: 54, favorites: ['food', 'movies']},
 {name: 'Mary Smith', age: 42, favorites: ['food', 'travel']},
 {name: 'Peter Pan', age: 15, favorites: ['minecraft', 'pokemo']},
 {name: 'Joe Johnson', age: 46, favorites: ['travel', 'movies']},
 {name: 'Ben Smith', age: 35, favorites: ['craft', 'food']}]
Expected Output
[
  "Smith",
  "Pan",
  "Johnson"
]
Actual Output
[
  "Smith",
  "Pan",
  "Johnson"
]
Solution
return _.uniq(_.map(data, function(d) {
    return _.last(d.name.split(' '))
}))