JS chaining functions - javascript

I'm writing a function that should work like this:
checker(3).equals(3) // true
checker(3).not().equals(3) // false
checker(3).not().equals(4) // true
checker(3).not().not().equals(4) // false
The code I came up with:
function checker(num) {
let number = num
return {
not() {
number = !number
return this
},
equals(nmb) {
return number === nmb
}
}
}
I can't wrap my head around what should not() do so as to make checker(num) work as it is supposed to.

You can add another boolean property that changes how equals works depending on it's value.
function checker(num) {
let number = num
let not = false
return {
not() {
not = !not
return this
},
equals(nmb) {
return not ? number !== nmb : number === nmb
}
}
}
console.log(checker(3).equals(3)) // true
console.log(checker(3).not().equals(3)) // false
console.log(checker(3).not().equals(4)) // true
console.log(checker(3).not().not().equals(4)) // false

Maybe somthing like this:
function checker(num) {
let number = num
let beTrue = true;
return {
not() {
beTrue = !beTrue;
return this
},
equals(nmb) {
return (number === nmb) === beTrue;
}
}
}
It seems to fullfil your requirements. Hope it helps

An ES6 approach
const checker=(number, negate)=>{
const neg = negate || false;
return {
not(){
return checker(number, !neg);
},
equals(number2){
if (neg) return number != number2;
return number == number2;
}
}
}
what should not() do so as to make checker(num) work as it is supposed to.
not could return a new checker.

I think i would let the notfunction control the operator, something like
function checker(num) {
let operator = 'equals';
let number = num
return {
not() {
if(operator==='equals')
operator = 'not equals';
else
operator = 'equals';
return this
},
equals(nmb) {
if(operator==='equals')
return number === nmb
else
return number !== nmb
}
}
}
just using a string as operator for clarity, a proberly better solution could be to use a boolean or number value

Related

Simplify semver version compare logic

There's the standard npm semver version comparison library, but I have some simple logic to compare semver versions here:
const versionA = '14.8.3';
const versionB = '15.1.1';
const versionC = '15.1.2';
const semver = require('semver');
const assert = require('assert');
const isGreater = (a, b) => {
const [majorA, minorA, patchA] = String(a).split('.').map(v => Number.parseInt(v));
const [majorB, minorB, patchB] = String(b).split('.').map(v => Number.parseInt(v));
if (majorA > majorB) {
return true;
}
if (majorB > minorA) {
return false;
}
if (minorA > minorB) {
return true;
}
if (minorB > minorA) {
return false;
}
if (patchA > patchB) {
return true;
}
if (patchB > patchA) {
return false;
}
return false;
};
assert(isGreater(versionB, versionA), 'version b should be greater.');
assert(isGreater(versionA, versionB), 'version b should be greater.');
my question is - is there a way to simplify the logic in the greaterThan function? This function is supposed to replicate the logic in semver.gt().
You can use localeCompare instead, with the numeric option (with numeric, comparison is such that "1" < "2" < "10"), which is exactly the logic you're looking for:
const versionA = '14.8.3';
const versionB = '15.1.1';
const versionC = '15.1.2';
const versionD = '15.1.10';
const versionE = '15.2.1';
const versionF = '15.11.1';
const isGreater = (a, b) => {
return a.localeCompare(b, undefined, { numeric: true }) === 1;
};
// first argument version comes later than second argument:
console.log(isGreater(versionB, versionA));
console.log(isGreater(versionC, versionB));
console.log(isGreater(versionD, versionC));
console.log(isGreater(versionE, versionD));
console.log(isGreater(versionF, versionE));
console.log('---');
// second comes before first:
console.log(isGreater(versionA, versionB));
// same, return value should be false:
console.log(isGreater(versionA, versionA));
Or, equivalently, you can pass the locale string
en-US-u-kn-true
as the second parameter instead of { numeric: true }.
I believe this is logically the same and shorter, but not exactly stunning in it's simplicity
const parseInt = (v: string) : number => {
const num = Number.parseInt(v);
if(!(Number.isInteger(num) && num > 0)){
throw new Error('Could not parse positive integer from string')
}
return num;
};
const isGreater = (a: string, b: string) : boolean => {
const [majorA, minorA, patchA] = String(a).split('.').map(parseInt);
const [majorB, minorB, patchB] = String(b).split('.').map(parseInt);
if (majorA !== majorB) {
return majorA > majorB;
}
if (minorA !== minorB) {
return minorA > minorB;
}
return patchA > patchB;
};

Recursion -finding the smallest number

I am lerning recursion and would like to know whats wrong with my solution. I am trying to find the smallest numbers using recursion(I know using a loop etc is much easier, but as I am learning recursion, I try to write a recursive function for that). Thanks!
function min(arr) {
if (arr.length==1){
return arr[0];
}
else if(arr[0]>arr[1]) {
return min(arr.slice(1));
}
else {
min(arr[0]+ arr.slice(2));
}
}
min([-5,4,0,8,5]);
The classic form of recursion applied to this problem would be:
function min(a) {
function smaller(a, b) { return a < b ? a : b; }
return a.length ? smaller(min(a.slice(1)), a[0]) : Infinity;
}
In ES6:
function min([head, ...tail]) {
function smaller(a, b) { return a < b ? a : b; }
return head === undefined ? Infinity : smaller(head, min(tail));
}
Here is an alternative approach, which passes the current minimum down to each recursive iteration. This has the advantage that it can be tail-optimized. Babel succeeds at doing that.
function min([head, ...tail], cur = Infinity) {
return head === undefined ? cur : min(tail, head < cur ? head : cur);
}
You need to use concat to join the arrays and not +. Try this:
function min(arr) {
if (arr.length==1){
return arr[0];
}
else if(arr[0]>arr[1]) {
return min(arr.slice(1));
}
else {
return min([arr[0]].concat(arr.slice(2)));
}
}
Here's a documentation link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
function recursiveMinNumber(items){
if(items.length === 1){
return items[0] //Base-case reached
}
else{
if(items[0]<=items[items.length-1]){
items.pop() //remove the last item in the array
return recursiveMinNumber(items)
}
else{
return recursiveMinNumber(items.slice(1)) //remove the first item in the array
}
}
}
console.log(recursiveMinNumber([2,22,3,3,4,44,33]))

excluding "missing" values in reductio.avg()

I was hoping to use reductio to compute averages within my crossfilter groups. My dataset includes missing values (represented by null) that I'd like to exclude when calculating the average. However, I don't see a way to tell reductio to exclude certain values, and it treats the null values as 0.
I wrote a custom reduce function to accomplish this without using reductio:
function reduceAvg(attr) {
return {
init: function() {
return {
count: 0,
sum: 0,
avg: 0
};
},
add: function(reduction, record) {
if (record[attr] !== null) {
reduction.count += 1;
reduction.sum += record[attr];
if (reduction.count > 0) {
reduction.avg = reduction.sum / reduction.count;
}
else {
reduction.avg = 0;
}
}
return reduction;
},
remove: function(reduction, record) {
if (record[attr] !== null) {
reduction.count -= 1;
reduction.sum -= record[attr];
if (reduction.count > 0) {
reduction.avg = reduction.sum / reduction.count;
}
else {
reduction.avg = 0;
}
}
return reduction;
}
};
}
Is there a way to do this using reductio? Maybe using exception aggregation? I haven't fully wrapped my head around how exceptions work in reductio.
I think you should be able to average over 'myAttr' excluding null and undefined by doing:
reductio()
.filter(function(d) { return d[myAttr] !== null && d[myAttr] !== undefined; })
.avg(function(d) { return d[myAttr]; });
If that doesn't work as expected, please file an issue as it is a bug.

Javascript square function

I want to write a function that checks if the given number has a certain order.
The second number has to be the square of the previous number.
The first number can only be 0 - 9.
So for example 2439 would return 'true' because 4 is the square of 2 and 9 is the square of 3.
39416 would also give 'true', and for example 1624 would return 'false'.
I don't really have an idea how to do this. It should be a recursive function but an example of how to do it without recursion would be helpfull too.
I would try something like this:
function isOrdered(input){
var position = 0;
while(position<input.length-2)
{
var currentFirstNumber = parseInt(input[position]);
if(currentFirstNumber<=2) {
if (Math.sqrt(parseInt(input[position + 1])) !== currentFirstNumber)
return false;
else
position+=2;
}
if(currentFirstNumber>=4 && currentFirstNumber<=9)
{
var squared = input.substring(position+1,position+3);
if(Math.sqrt(parseInt(squared))!==currentFirstNumber)
return false;
else
position=position+3;
}
}
return true;
}
console.log(isOrdered("2439")); // outputs true
console.log(isOrdered("39416")); // outputs true
console.log(isOrdered("1624")); // outputs false
I pass the number to the function as a string.
Take a look at this recursive function
function detectOrder(input)
{
var input = input.toString()
var first = input.substr(0,1);
var power = Math.pow(parseInt(first), 2);
var powerLength = power.toString().length;
if ( parseInt(input.substr(1, powerLength)) == power )
{
if (input.length <= 1+powerLength)
{
return true;
}
else
{
return detectOrder(input.substr(1+powerLength));
}
}
else
{
return false;
}
}
As mention in the comment section, OP said that the 'firsts' are limited to 0..9. So the easiest way to accomplish this is by going through the power function instead of the square root function.
UPDATE: Sorry, you asked for JavaScript code. Be careful with the FIRST CALL. if you manually pass to the function the last position, it will return true.
function verification(number, position){
var str = String(number); // Cast number to String
if(str.length > position){ // Verify valid position
var value = str.substr(position, 1); // take the 'first' value
var pow = Math.pow(value, 2); // Calculate the power
// Verify if the next value is equivalent to the power
if(str.indexOf(pow, position) == position + 1){
// Recursive call to verify the next position
return verification(number, position + String(pow).length + 1);
} else {
// If not equivalent, you found an inconsistency.
return false;
}
// If you ran it until you reached the last position, you're good to go.
}else if(str.length == position){
return true;
}
}
console.log(verification(39416, 0)); // True
console.log(verification(39415, 0)); // True
console.log(verification(981524, 0)); // false
console.log(verification(981525, 0)); // true
console.log(verification(98525, 0)); // false

Best way to implement Javascript chaining in a library

I'm creating a JavaScript library. I've been trying to implement chaining.
0: What I first came up with:
function V(p) {
return {
add : function(addend) { return V(p + addend); },
sub : function(subtra) { return V(p - subtra); },
};
}
Using this method I can chain easily:
V(3).add(7).sub(5) // V(5)
Unfortunately the result is always a wrapped V() function, I am unable to extract the resulting value this way. So I thought about this problem a bit and came up with two semi-solutions.
1: Passing flag to last method
function V(p, flag) {
if(flag)
return p;
else
return {
add : function(addend, flag) { return V(p + addend, flag); },
sub : function(subtra, flag) { return V(p - subtra, flag); }
};
}
Using this method I can end the chain by passing a flag to the last method I use:
V(3).add(7).sub(5, true) // 5
While this works just fine, it requires some code repetition and makes chaining less readable and my code less elegant.
2: Using start() and end() methods
_chain = false;
function V(p) {
function Wrap(w) {
return (_chain) ? V(w) : w;
}
return {
add : function(addend) { return Wrap(p + addend); },
sub : function(subtra) { return Wrap(p - subtra); },
start : function() { _chain = true; },
end : function() { _chain = false; return p; }
};
}
Using this method you can do single operations with no more code:
V(3).add(7) // 10
But chaining requires two more methods, making things a lot less readable:
V(3).start().add(7).sub(5).end() // 5
So basically I'm just searching for the best way to implement chaining into my library. Ideally I'm looking for something where I can use any number of methods and don't need to terminate the chain in inelegant ways.
V(3).add(7).sub(5) // 5, perfect chaining
Why not introducing a private variable and work on that? I guess that is even more convenient. Plus it's probably a good idea to have a pure "getter" that finally returns the computed value. This could look like this:
function V(p) {
var value = p;
return {
add: function(addend) {
value += addend;
return this;
},
sub: function(subtra) {
value -= subtra;
return this;
},
get: function() {
return value;
}
};
}
console.log(V(3).add(7).sub(5).get()); // 5
You cannot return the Object in a getter function obviously. So you need some method where the chaining ends and returns a value.
In some cases it does need to have something similar to end, but in your simple arithmetic example, it does not.
function V(initial_val){
if(!(this instanceof V)){
return new V(initial_val);
}
var num = initial_val || 0;
this.set = function(val){
num = val;
return this;
}
this.add = function(val){
num += val;
return this;
}
this.sub = function(val){
num -= val;
return this;
}
this.valueOf = function(){
return num;
}
this.toString = function(){
return ""+num;
}
}
By adding valueOf and toString functions to the object, you can access its primitive value. That is, you can do something like:
var num = V(0).add(1).sub(2), another_num = 3 + num; // num = -1 and another_num = 2;
I would amend Haochi's excellent answer as follows :
Using the prototype will be more efficient if you have many V objects and
in the toString function I invoke the generic number toString with whatever
arguments you care to give it.
function V (n) {
if (!(this instanceof V)) {
return new V (n);
}
this.num = +n || 0;
return this;
}
V.prototype = {
set: function (val) {
this.num = val;
return this;
},
add: function (val) {
this.num += val;
return this;
},
sub: function (val) {
this.num -= val;
return this;
},
valueOf: function () {
return this.num;
},
toString: function () {
return this.num.toString.apply (this.num, arguments);
}
}

Categories

Resources