In one of my Flatiron coding challenges, I had to make an anagram tester that would test which words in an array were anagrams of the target word. Possible anagrams were passed to a
#match method through an array. The
#match method would then be called on an Anagram object and “collect” all the words that matched as an anagram. For example:
listen = Anagram.new("listen") listen.match(%w(enlists google inlets banana)) # => ["inlets"]
As I wanted to “collect” all the matches, at first I attempted to use
#collect on the array.
class Anagram attr_accessor :word def initialize(word) @word = word @letters = @word.split("").sort end # find anagram matches given an array of words def match(possible_anagrams) possible_anagrams.collect do |possible_anagram| @letters == possible_anagram.split("").sort end end end
The problem with
#collect, however, is that it collects all of the return values produced by the code in the block, so I was getting an array full of the values that were returned by the block's expression.
listen.match(%w(enlists google inlets banana)) was returning
=> [false, false, true, false]. What I really needed was to get just the items in the array that made the code block return true.
Guess who can do that? You guessed it:
#select! Switching out
#select solved the problem:
class Anagram attr_accessor :word def initialize(word) @word = word @letters = @word.split("").sort end # find anagram matches given an array of words def match(possible_anagrams) possible_anagrams.select do |possible_anagram| @letters == possible_anagram.split("").sort end end end
Now only the items that made the block true would be included in the returned array: => ["inlets"].
The difference is super clear if you check the Ruby documentation:
- #collect: “Creates a new array containing the values returned by the block.”
- #select: “Returns a new array containing all elements of the array for which the given block returns a true value.”
Okay, so what about
#map? It turns out #map is the exact same thing as #collect. A lot of times you’ll hear that certain functions do the same thing, but in truth there are actually slight differences. In the case of
#collect, though, they are identical down to the source code. Check for yourself by clicking the “click to toggle source” under the #collect and #map documentation!
Edit: Initial code refactored based on discussion comments below (thank you!)