I have a sort function, let's call it mySort(a, b) that returns 1,0,-1 if a is smaller. equal, bigger than b. That way, I can do a myArray.sort(mySort) to sort my array.
I now have a view where the array needs to be sorted in a descending order. My first solution was to just do myArray.sort(mySort).reverse() (yes, I know it's not efficient, but the array contains less than 50 items). But I started thinking that maybe I can just add another parameter to my sort function, that will return the opposite result if set to false: mySort(a, b, ascending = true).
The problem is: if I want to use Array.sort I need to provide a function. Is there a way to use apply (or call?) to create a function that will have ascending set to false, in a way that would allow something like myArray.sort(myFunction.apply(null, [,,false]))? Because I don't see a way to provide a and b on the fly.
You can use mySort.bind() to bind a context and initial arguments, but I don't think there's anything like that that will force later arguments while leaving the first 2 arguments alone.
You can use a wrapper function that adds an argument:
myArray.sort((a, b) => mySort(a, b, true));
or reverses the sign of the result:
myArray.sort((a, b) => -mySort(a, b));
or swaps the argument order:
myArray.sort((a, b) => mySort(b, a));
You can also create a higher order function that implements this.
function reverseArgs(func) {
return function() {
return func.apply(this, Array.from(arguments).reverse());
};
}
myArray.sort(reverseArgs(mySort));
This is an alternate solution, but I'd just wrap your sort function in another function.
function myRevSort(a, b) {
return mySort(a, b) * -1;
}
Or, if you want a boolean flag (although that generally isn't recommended), you can just use it to pick the multiplier, then return a "sorter" function:
function newSorter(ascending = true) {
var mult = ascending ? 1 : -1;
return function(a, b) {
return mySort(a, b) * mult;
}
}
Then use it like:
myArray.sort(newSorter(false));
A note though, I think "comparator" is a more appropriate name for these functions. sort sounds like the function that actually sorts the collection.
Related
I am reading right now the source code of Ramda and don't understand the point of _curry1().
function _curry1(fn) {
return function f1(a) {
if (arguments.length === 0 || _isPlaceholder(a)) {
return f1;
} else {
return fn.apply(this, arguments);
}
};
}
Functions that are curried with this function can be called without arguments.
const inc = (n) => n + 1
const curriedInc = _curry1(inc)
// now it can be called like this
curriedInc(1) // => 2
curriedInc()(1) // => 2
// but it works only with no arguments provided
const add = (a, b) => a + b
const curriedAdd = _curry1(add)
curriedAdd(1) // => NaN
curriedAdd(1)(1) // => TypeError: curriedAdd(...) is not a function
curriedAdd() // => function f1(a)
Question:
It seems to me that you can't chain arguments with this function at all. What are use cases for this function? How different is curriedInc()(1) from inc(1)?
_curry1, _curry2, and _curry3 are performance-boosting tricks that can't be used in the public curry function. Ramda (disclaimer: I'm an author) uses them to perform several tasks, clearly mostly doing the currying, but also checking for placeholders so that we can properly do some partial application. The other magic thing about Ramda's currying is the way that you can apply all, some, or even none of the required arguments, and so long as we're not complete, you get back another function looking for the remaining ones.
Obviously _curry1 theoretically shouldn't be necessary, but it makes it easier to add this sort of consistency:
const a = curry ((a, b, c) => ...)
a (1, 2, 3) == a (1, 2) (3) == a (1) (2, 3) == a (1) (2) (3) == a () () (1, 2) () (3)
Notice that last one. When you call a curried function still looking for arguments with no arguments at all, you get back the same function.
curry1 is what makes that happen; it adds consistency. But that's all it's for.
I don't have much practice with recursion and I have only some experience with javascript.
How do I refactor the code below to use recursion instead of the for loop?
function add(a, b) {
var sum = 0;
for (var i = a; i <= b; i++) {
sum += i;
}
return sum;
}
console.log(add(3,7)); //25
The for loop makes sense to me; recursion not so much.
EASY WAY:
function recursive(a, b)
{
if(a > b)
{
return 0;
}
return a + recursive(a+1, b);
}
console.log(recursive(3,7));
HARD WAY: (EASY + EXPLANATION)
What is a recursion in a common programming language?
according to Wikipedia: Recursion in computer science is a method where the solution to a problem depends on solutions to smaller instances of the same problem (as opposed to iteration).
translated in everyday language a recursion is when you iterate n-times a function(in this case) and every time that the function call hisself wait for the result of the invoked function's instance.
The invoked functions's intance will invoke himself another time and wait for the result.
When this endless loop will stop?
When an instance will finally return a value, this happens typically with a check before the recursive call(see the easy way).
When a function will return a value all the knots will be loose and the first function that started the cycle will return the final value.
if you want to go deep or just my short explanation was not convincing i reccoment you to read this article: https://www.codecademy.com/en/forum_questions/5060c73fcfadd700020c8e54
You could use another parameter for the sum of the last call, for a later tail call optimisation of the recursive call.
At start, initialize s which keeps the summed result and add a.
The perform an exit check, if the target value is reached, then exith with the sum s.
Otherwise call the function again with reduced start value, given end value and the actual sum of all.
Don't forget to return the value of the call.
function sum(a, b, s) {
s = s || 0;
s += a;
if (a === b) {
return s;
}
return sum(a + 1, b, s);
}
console.log(sum(3, 7));
Without tail optimization, this keeps all intermediate results in stack.
function sum(a, b) {
if (a === b) {
return a;
}
return a + sum(a + 1, b);
}
console.log(sum(3, 7));
I'm attempting to allow user defined logic criteria. Since the user definitions are basically strings, I'm trying to make the code efficient by avoiding string comparison. For example, a simple test like a == 10 would be represented by an array
var userDef = ['a', '==', 10]
To make the logic evaluation efficient, I'd like to create an object like the ffg:
var binaryOperator = {'==': 0, '>': 1, '<': 2}
.. so when I mine the array, I could do e.g.
if(binaryOperator[userdef[1]] == 0)
{
return (obj[userDef[0]] == userDef[2])
}
... where of course obj.a = something. The above code, on the face of it, avoids string comparison.
But does it really? Is the reference binaryOperator[userdef[1]] really fast or does it also involve string comparison somewhere?
In other words is there a performance difference between thisObj.a and thisObj['a']?
You could omit the check for the operator and take a function as value, like
var binaryOperator = {
'==': function (a, b) { return a === b; },
'<': function (a, b) { return a < b; },
'>': function (a, b) { return a > b; }
};
Objects in Javascript have an access of O(1).
Further readings:
Performance of key lookup in JavaScript object, JS engine desings
JavaScript object structure: speed matters, by using a fully defined object instead of adding properties at run time.
Given an object and a key, getElementsThatEqual10AtProperty returns an array containing all the elements of the array located at the given key that are equal to ten.
I want to assign what my .reduce method outputs to a variable then use that variable inside my if statement. My code evaluates to NaN.
function getElementsThatEqual10AtProperty(obj, key) {
var arrayTotal = 0;
obj[key].reduce(function(a,b){
arrayTotal = a + b;
});
if(arrayTotal === 10) {
return obj[key];
}
};
You're approaching reduce incorrectly. You're almost using it like Array#forEach. Remember that callbacks are functions. They expect to return an actual value.
When you read the docs, you'll see that reduce also needs an accumulator, that is an argument after the callback.
const sum = obj[key].reduce(function(a,b){
return a + b
}, 0)
Or if you want the newer and prettier version:
const sum = obj[key].reduce((a,b) => a + b, 0)
When you have a one liner, return is implicit, which means it's implied, as opposed to explicit.
The accumulator is what your value starts at while it totals up the values.
Array.reduce(callback, accumulator)
I have an array of arrays:
var data = [[2,2], [6,4], [300,500]];
I have a function that takes some arguments and returns a single value.
var sum = function (a, b) { return a + b; }
I want to apply the function to each item in the array, e.g.
FOO(data, sum) === [sum(2,2), sum(6,4), sum(300,500)] === [4, 10, 800]
I was hoping underscore would have a function that does what "FOO" does. But I don't see anything. _.map is close, but not quite.
I know how to implement the function FOO.
var FOO = function (arrayOfArrays, iterator, context) {
return _.map(arrayOfArrays, function (array) {
return iterator.apply(context, array);
}
)};
My question is what to call FOO. I'm guessing the above pattern is common enough in functional programming that there's already a well established, language-agnostic name for this function.
It seems to me there is already a standard Javascript method for arrays, forEach(), that does what you want. For example:
data.forEach(sum);
So, do you really need a new FOO? If so, you could name it "forEach" and just wrap the above logic.