Item 35: Use map and grep to manipulate complex data structures.
Sometimes it's useful to take a "slice" out of a multidimensional array or hash, or to select slices that have certain characteristics. Conversely, you may need to assemble a collection of lists into a 2-D array, or perhaps assemble a collection of 2-D arrays into a 3-D array. Perl's map and grep operators are a perfect choice for chores like these.
Slicing with map
Let's begin with a program that reads a file containing 3-D coordinates into memory:
Reading a file of 3-D coordinates into memory
The point data is read into a structure that looks like the following:
Now, let's suppose you would like to have just the x (0th) element from each point, as indicated by the shading in the figure. You could write a loop using an explicit index, or perhaps use a foreach loop:
But, really, this is a natural application for map :
Use map to take slices of complex data structures.
Nesting with map
On the other hand, suppose that you are starting out with parallel arrays @x , @y , and @z containing vectors of points:
You now would like to assemble them into a single 3-D structure like the one shown earlier. Once again, you could use some sort of explicit looping structure:
However, map provides a much more elegant alternative:
Use [ ] inside map to create more deeply nested structures.
No doubt you can envision a host of variations on the slicing and nesting themes. For example, switching the x (0th) and y (1st) coordinates:
Or, perhaps, creating a new list containing the magnitudes of the points:
The Schwartzian Transform (see Item 14) is an application that uses both slicing and nesting operations with map :
Selecting with grep
Suppose that you would like to filter @xyz so that it contains only points whose y coordinate is greater than its x coordinate.
You could write a loop (how did you guess I was going to say that?):
But this time, we have a task that is perfectly suited to grep :
Use grep to select elements from nested structures.
Of course, you can combine map and grep for example, to gather up the x coordinates of the points with y greater than x :