Introduction
The Schwartzian transform -- also known as map-sort-map or decorate-sort-undecorate (DSU) --, attributed to Randal Schwartz of the Perl community, sorts elements of a list or array by a metric which maps each element to its “sort value”.
Example for those who are not familiar with the Schwartzian transform
For instance in Python 2.4 and above, both the sorted()
function and the in-place list.sort()
method take a key
parameter that allows us to provide a special "key function".
This function is simply called on each list element before making comparisons and thus cleverly avoids computing the criterion value every time.
In other words, sorting a (Python) list of strings case-insensitive:
>>> sortList = ["the", "Schwartzian", "Transform", "rocks"]
>>> sortList.sort(key = lambda e: e.lower())
['rocks', 'Schwartzian', 'the', 'Transform']
This could be also split into the 3 basic steps Schwartz suggests:
#1: Turn the list into an array of references to pairs
>>> temp = [(e.upper(), e) for e in sortList]
>>> temp
[('THE', 'the'), ... , ('TRANSFORM', 'Transform'), ('ROCKS', 'rocks')]
#2: Sort this list by the second elements
>>> temp.sort()
#3: Turn the sorted list back into one one value list
>>> sortList = [e[1] for e in temp]
>>> sortList
['rocks', 'Schwartzian', 'the', 'Transform']
The Question
Now I wonder if other well-known programming languages like C++, C#1), Java, JavaScript, VisualBasic and so on provide Schwartzian transform like interface too or is a "workaround" (a own implementation rather than a language feature) needed instead like this sample in C#:
var unsorted = new string[] { "the", "Schwartzian", "Transform", "rocks"};
var sorted = unsorted.Select(word => new { word, lower = word.ToLower() })
.OrderBy(t => t.lower)
.Select(t => t.word)
.ToArray();
1) As far as I know it’s possible using the Linq syntax
unsorted.OrderBy(t => t.ToLower())
looks like Schwarzian transform to me.OrderBy()
only calls the key function once for every item in the list, you can test it yourself. PuttingSelect()
aroundOrderBy()
is unnecessary.