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.
With #collect
, the 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 #collect
for #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 #map
and #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!)