-
-
Save ChrisWhealy/b8c873a7753fc17ce0131c654caf60fa to your computer and use it in GitHub Desktop.
/*********************************************************************************************************************** | |
* Partition an array into two arrays based on passing each element to a predicate function. | |
* | |
* This function is designed to extend the Array prototype, but only by the explicit action of the consuming library. | |
* E.G. Assuming the function below belongs to a "utils" module, you must write something like the following: | |
* | |
* const utils = require('./utils.js') | |
* Array.prototype.partitionWith = utils.partitionWith | |
* | |
* This function must be defined using a traditional "function" declaration instead of an arrow function. If an arrow | |
* function were used, then the reference to "this.reduce" wouldn't work... | |
* | |
* partitionWith takes a simple predicate function as an argument and returns an array containing two other arrays. | |
* The first array contains all the elements that do not match the predicate, and the second, all the elements that do | |
* match the predicate | |
* | |
* E.G. | |
* | |
* var isEven = x => x % 2 === 0 | |
* var numbers = [1,2,3,4,5,6,7,8,9,10] | |
* var [odd, even] = numbers.partitionWith(isEven) | |
* | |
* odd = [1,3,5,7,9] | |
* even = [2,4,6,8,10] | |
*/ | |
const partitionWith = function(predFn) { | |
const partitionReducer = (acc, el) => | |
(success => success ? [acc[0], acc[1].concat(el)] | |
: [acc[0].concat(el), acc[1]]) | |
(predFn(el)) | |
return this.reduce(partitionReducer, [[],[]]) | |
} |
I have no problem with single cases of x
over xs
, but when you're looking at a reasonably deep stack trace containing lots of functions that all use single letter variable names like names like f
and a
and b
, you (or more specifically, I) quickly loose track of what value is stored where. Quinsiquontly, in my attempt to remove any ambiguity, I tend to use longer, self-descriptive names
The preference of partitionWith
over partition
is motivated by the same reasoning
Alles sollte Idiotensicher sein, weil manchmal, bin Ich das Idiot...
:-P
Goodness me you wouldn't believe how lovely Ramda's implementation of partition
is. Might be worth a beer and a live stream to look at it...
Yes, the Ramda implementation is:
partition = juxt([filter, reject])
Where juxt
first applies the filter
function to produce the first array, then its logical complement reject
to produce the second array
Thanks Chris, I did think it might be related to academic principles (I know you very well!)
Interesting term, "meaning obscuring". I quite like
f
,a
,b
,x
andxs
and think that they help, rather than obscure. Theoretically they should also force (or at least persuade me to think about) splitting out logic into further separate functions if it all gets "a bit too much". But I know some folks see that differently. I subscribe to the Erik Meijer school of "x over xs".partition
vspartitionWith
- interesting too - Ramda calls it partition. After a beer, I'd argue that the 'with' was superfluous, as (almost) "of course you're going to provide a predicate function" :-)