How many times have you had to display a list of items like this:
apples - oranges - ququxes - bananas
The newbie programmer (like I myself was and still am in many respects) will often hammer out this piece of code:
String output = "";
for( int i = 0; i < fruits.size(); i++ ) {
output += fruits.get(i);
output += " - ";
}
// Now remove the last separator
output = output.substring( 0, output.length() - 3 );
Hey, this is convoluted and ugly. There should be a library function that does this for us. Everybody uses arrays and strings. This is such a basic problem that someone must have already implemented it in some library somewhere, if it’s not already in our language’s standard library.
So let’s turn to Google, to find a library that can save us.
But … what search terms should we use?
In other words, what is this problem’s name?
Once you can name something, you can master it. This is a thought that stuck with me while reading the classic introductory textbook to programming, Structure and Interpretation of Computer Programs.
We learn new words, and even make up new words, because it helps us communicate and understand ideas and thoughts of ever increasing complexity.
Take a simple sentence, like The government will lower taxes. Now try to express the same idea, with the same precision, but without using the words government, or taxes. You’ll end up with something like: “The body of individuals elected by the people of a country, with a limited-time mandate to run the country, will lower the amount that each individual must contribute to support the country’s shared expenses.” Not pretty, by any measure.
Enough with the theory, let’s return to the craft of programming.
There exist a bunch of simple but very common problems, involving arrays and strings. And I want to remind you that they have names, and how important it is to know these names. It will help you not only in finding the right library call to do what you are trying to do, but it will also help you recognise these problems in your day to day programming work. You’ll be able to think Hey, this looks like a map followed by a select, I know exactly how to solve it quickly and elegantly.
join
Let’s backtrack for a minute to the start of this post. What we have there is a problem that can be summarised as:
["apples", "oranges", "ququxes", "bananas"]
=> “apples - oranges - ququxes - bananas”
In plain English: we have an array of strings and we want to join together these items into a single string, with a separator string in between the items.
This problem has a classic name, it’s called a join.
Now we know how this problem is called, we can master it. We started out this example in Java, so we’ll have to find a Java library function that does join. And sure enough, commons-lang’s StringUtils class has a helpful little method called join().
Side note: If you use one of the more friendly languages out there, like Python or Ruby, you’ve got it easier. In Ruby it’s as simple as:
irb(main):001:0> ["apples", "oranges", "ququxes", "bananas"].join(” - “)
=> “apples - oranges - ququxes - bananas”
split
"apples - oranges - ququxes - bananas"
=> ["apples", "oranges", "ququxes", "bananas"]
This is the reverse of join. Take a string of items separated by a delimiter, and return an array of the individual item strings.
There’s a split function in the standard library of Python, Ruby, PHP, even Java. Oh yeah, in Java it’s as simple as string.split(pattern).
zip
A zip operation, also called combine, means pairing each corresponding item from two arrays:
["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
[31, 28, 31, 30, 31, 30 ]
=> ["Jan", 31],
["Feb", 28],
["Mar", 31],
["Apr", 30],
["May", 31],
["Jun", 30]
It’s called array_combine() in PHP, and zip in Ruby.
flatten
Taking a nested array (aka array of arrays) and turning it into a, err, flat array:
["one", ["two", "three"], “four”, ["five", ["six", "seven"]]]
=> ["one", "two", "three", "four", "five", "six", "seven"]
map
map, also called collect, transforms each item of an array through a function that you specify, and returns an array of the transformed values. Classic example: finding out the squares of the first positive integers:
[1, 2, 3, 4, 5, 6]
=> [1, 4, 9, 16, 25, 36]
To achieve this, you pass in a function that takes the argument x and returns x*x. Exactly how you do this varies according to your language. In some languages it’s braindead simple (Ruby), in others it requires a bit more work but still reasonably simple (PHP, Java)
reduce
reduce, also called inject, combines all the values of an array using a function that you specify, to create a single value. Simple example: the sum of all the elements of an array of numbers:
[1, 2, 3, 4, 5, 6]
=> 21
is a reduce operation where you pass a function of two arguments a and b that returns a+b.
Just like with map above, how you do it varies according to your language. Take a look at Ruby, PHP. I can’t find a similar function for Java, if you know any, please react in the comments section
select, reject
These are filters, they retain or remove items from an array according to a function you pass in.
Let’s filter only the items that start with a vowel:
["apple", "banana", "cherry", "orange", "plum"]
=> ["apple", "orange"]
All you do is call “select” and pass in a function that returns true if its argument starts with a vowel. That’s a function you’ll have to build for yourself, sorry
reject works the same way but returns the items that do not match the function. Using the same function as above, a call to reject works this way:
["apple", "banana", "cherry", "orange", "plum"]
=> ["banana", "cherry", "plum"]
Of course, if your language or libraries don’t provide a reject call, you can use select and pass in a function that returns false when it was supposed to return true.
Have a look at array_filter if you’re using PHP, select or reject if you’re using Ruby, or commons-collections’ select and selectRejected if you’re using Java.
OK, kids, I hope you learned something today
Start recognising common patterns like join or map in the code that you write, and start thinking in terms of them.
Please feel free to suggest additional code samples and links for the languages I have not covered.