Translating Pig Latin with Flatten and Reduce
Explore how to manipulate observable streams with RxJS by translating English sentences into Pig Latin. Learn to use flatten and reduce operators to process arrays and handle edge cases in a practical reactive programming example.
We'll cover the following...
Pig Latin is a silly pseudo language based on English. Translating an English sentence into Pig Latin is simple. Split each sentence into words and put each word through the following modifications:
-
Remove the first letter of each word: “Pig Latin” becomes “ig atin” (exception: ignore single-letter words)
-
Add the first letter removed in the previous step plus “ay” to the end of the word: "ig-pay atin-lay"
Alas, nothing is ever that simple, and there’s an edge case we need to worry about: single-letter words (specifically, a and I). To keep it simple, our code will let it be and return the word unchanged in the event of a single-letter word.
📝 Advanced Pig Latin
Like any natural language, there are many dialects of Pig Latin. Some break things down further, checking whether the word starts with a consonant or a vowel. We’re just using a simplified Pig Latin as an example here. If you want to add more rules after you finish this section, go for it!
Pig Latin function
Pig Latin is enormous fun to say aloud. Some folks are even able to have full conversations in it without missing a beat. On the other hand, we want to write a program to do all that work for us. Translating the single-word rules to JavaScript results in this function:
You can use the techniques from the last chapter (fromEvent and map) to connect this function to a textbox that prints out a Pig Latin translation on every keystroke:
Pig Latin translator project
A quick review:
-
Every
keyupevent is sent down the stream by thefromEventconstructor. -
The first
mapextracts the value of the textbox. -
The second
mapsplits the string using a regex that matches one or more instances of whitespace (\s: match whitespace,+: one or more instances). -
The final
maptakes the array of words and passes each word through the translation function (usingArray.prototype.map).
📝 Chaining operators
In the previous example, technically, three map operators could be combined into a single (if somewhat complex) operator:
map(event => event.target.value.split(/\s+/).map(pigLatinify))In fact, in older versions of Rx, munging everything together into a single operator would increase performance at the cost of readability, because every operator technically created a new observable at the library layer. Version 5 (and beyond) of RxJS solved that problem. In the case of combinable operators, RxJS merges the functions at the library level, improving performance without sacrificing simplicity. A win all around.
The three-map snippet works just fine, but it’s only one of many possible ways to implement a real-time translator.
In the next section, you’ll see some new techniques used to the same effect, but they provide building blocks that the rest of the course will expand on.
The first of these is the idea of the function that flattens multidimensional collections so we can better handle that array of words.
Pig Latin application
Here’s the code for the complete application.