Naming and Some Common String and Array Patterns 8

Posted by Iulian Dogariu on September 25, 2008

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 :-P

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.

Not a minute too soon 3

Posted by Iulian Dogariu on July 04, 2008

37signals announces their end of support for IE 6. They are actually the second high-profile web app developer to drop IE 6, after Apple did the same with MobileMe. The snowball is rolling. The lives of web developers will improve dramatically when they will no longer have to ensure support for the decrepit browser that IE 6 is.

Macros in Javascript?

Posted by Iulian Dogariu on June 19, 2008

Quick ramble. Say you wanted to add support for macros in Javascript:

* to support the unless construct by using the “if” construct: unless( condition ) { alert(”Condition is false”); }
* to support fancy for loops in terms of the while loop.

What would be a good syntax for describing such macros? Here are some thoughts that crossed my mind:


macro unless($cond) ${} {
  if(!($cond)) ${}
}

macro for($init; $cond; $loop) ${} {
  $init;
  while($cond) {
    ${}
    $loop;
  }
}

The line starting with macro is a pattern matcher, the $variables capture the key parts. The ${} token captures an entire block. Then, between { and }, comes the expanded form.

What do you think?

On Managers

Posted by Iulian Dogariu on March 25, 2008

“Managers are not schooled in radical change. The elimination of entire industries and their replacement with others, the obsolescence of established products in periods measured in months, the consequences of continued exponential growth in technology are all foreign to the manager. Presented with a problem, an expert manager can quickly grasp its essence and begin to formulate a plan to manage the problem on an ongoing basis. But what if the problem can be fixed? This is not the domain of the manager.”

“Management in isolation struggles with constraints that can frequently be eliminated. Engineering in isolation seeks permanent fixes which sometimes don’t exist and, even when found, often require an ongoing effort to put into place and maintain. Each needs the other to truly solve a problem.”

John Walker, founder of Autodesk

More focus

Posted by Iulian Dogariu on February 18, 2008

Particularly observant readers may have noticed that I swept all non-technical posts out of this blog. From now on, their new home is http://www.jayomega.net/nc/, a secondary blog dedicated to rants and musings of a “less-professional” nature. There I’ll be speaking mostly to my Romanian readers. If you do read Romanian however, please drop by ;-)

JavaScript 2: An alternative proposal

Posted by Iulian Dogariu on February 17, 2008

The ECMAScript version 4 specification is almost ready. ECMAScript 4 will be the basis of JavaScript 2. And, omg, it’s huge! Like, literally huge. Here you can read a digest of the proposed language features.

I feel that the proposal is non-orthogonal (read: bloated) in many ways. The new language will have both class-based OOP, a la Java, and prototype-based OOP; packages and namespaces as logical units of code; static type annotations both of the nominal kind (this object IS A Thing), and of the structural kind (this object responds LIKE a Thing).

What if, instead of striving to clone Java, they focused on making ECMAScript a more pleasant language to develop in? What if they:

  • added interpolated strings. Yes, I like to write alert("Hello, ${name}, welcome to JS!"); instead of alert("Hello, " + name + ", welcome to JS!");
  • added a simpler syntax for passing functions as arguments. How about this:
    [1,2,3].each() do (item) {
        alert(item)
    }
    

    as syntactic sugar for this JavaScript construct:

    [1,2,3].each( function (item) {
        alert(item)
    } );
    
  • got rid of nominal types. JavaScript can do OOP really well without classes, and it’s a shame to shoehorn classes and interfaces into it just to imitate Java and C#
  • shipped a unit testing framework in the standard library
  • added useful methods on arrays, like map, inject, detect, any, all

Eh? How about you? What do you wish to see in the next major version of Javascript?

Later Edit: Also see Douglas Crockford’s suggested changes.

[tags]es4,javascript[/tags]

What’s in a (function) name

Posted by Iulian Dogariu on November 10, 2007

The name of a function I found while reviewing some C# code:

IsIntervalContainsStaticOrOtherIntervalIP

Though, to be fair, the author’s mother tongue was not English.

Steve Jobs: Stay hungry, stay foolish

Posted by Iulian Dogariu on August 16, 2007

Using prototype.js in chrome 9

Posted by Iulian Dogariu on February 09, 2007

Are you writing a Firefox/Thunderbird extension, or maybe a XULRunner app, and want to make use of the excellent Prototype JS library? Then you will run into this issue.

Because of a long-standing bug in Mozilla, Function.prototype cannot be extended with the method ‘bind’, and so all the utilities in Prototype.js that make use of bind() won’t work as expected. Once again, this happens with documents loaded from _chrome_, not with normal web pages.

Steve Conover posted a workaround for this bug, about a year ago. I’m happy to offer a patch against Prototype 1.5.0 (final), with that workaround applied. Hope you’ll find it useful.

What does this code do?>:)

Posted by Iulian Dogariu on January 27, 2007

#!/usr/bin/ruby

       m,yiel=0,proc{yie(ARGV[0]){|y|
    print y;m+=1;print m%8==0?”\\n”:”\\t”}}
  class String;def yi(e);e.times{|i|y=self.
    dup;y[i]=”";yield(y,self[i].chr)}end;
      def if;yee==0; end; def yee;self.
        length;end; end; def yie(y);
          yield y  if y.if; y.yi \\
            (y.yee) { |ii,y| yie\\
             (ii){ |ye|   yield\\
               y+ye } }   end;
                 yiel.call()
                  puts  ”
                  n=#{m}”

[tags]ruby, obfuscated[/tags]