const semvers = ["5.100.0-rc.0", "5.97.3", "5.97.1"];
const newRecord = "5.97.2";
Given the above test data, I wish to insert newRecord into the right order, defined/sorted by semver package.
result = ["5.100.0-rc.0", "5.97.3", "5.97.2", "5.97.1"];
Below is my attempt which gave me the correct result
const semvers = ["5.100.0-rc.0", "5.97.3", "5.97.1"];
const newRecord = "5.97.2";
const indexResult = R.findIndex(x => semver.lt(x, newRecord))(semvers);
const result = R.insert(indexResult, newRecord, semvers)
Then, i was wondering if I can replace x with R.__, so i attempted below
const indexResult = R.findIndex(semver.lt(R.__, newRecord))(semvers);
I had the impression that R.__ referring to the arguments that was gonna passed but seems like it's not, or it was simply due to the fact that semver.lt is not a curried function and hence couldn't comprehend R.__?
R.__ works with Ramda functions or functions curried with Ramda e.g.,
const semvers = ["5.100.0-rc.0", "5.97.3", "5.97.1"];
const newRecord = "5.97.2";
const findVer = R.curryN(2, semver.lt)(R.__, newRecord);
const indexResult = R.findIndex(findVer, semvers);
const result = R.insert(indexResult, newRecord, semvers);
My preferred option would have been: R.flip(semver.lt)(newRecord) unfortunately semver.lt arity is 3 (third argument is a loose parameter) so R.flip doesn't work straight out of the box.
With R.partialRight you could supply the last two arguments (including that undocumented (?) loose parameter):
const findVer = R.partialRight(semver.lt, [newRecord, false]);
But honestly what you had originally is fine.
Related
I have this Code in my Javascript File:
const blfTypeAndId = DDid.split("PrerequisitesSelect");
const blfType = blfTypeAndId[0];
const blfId = blfTypeAndId[1];
The blfType is after this either 'block', 'line' or 'field' and the blfId is _B1_L1_F1 while the numbers can be different (this is just for field, for line it would be _B1_L1 and block just _B1)
In a world where Python and Javascript are combined I would just do this:
const blfType, const blfId = DDid.split("PrerequisitesSelect");
Is there a nice way in Javascript to still do this in one line or is my first written code already the best possible solution?
A good job for the Destructuring Assignment
const blfTypeAndId = DDid.split("PrerequisitesSelect");
const [blfType, blfId] = blfTypeAndId;
or even just
const [blfType, blfId] = DDid.split("PrerequisitesSelect");
"Use reduce and the hex2color function to count list of hex values than have r in their name";
My current attempt is below. The first piece I know needs to be fixed is the filter function. I need to be able to filter out any colors that have the letter "r", but cannot seem to find a way to easily fit that into the filter function. It could easily be a syntax issue as I think I am asking the filter to find any strings that === "r", even though I am trying to use "contains" to solve that and have it check the whole color word.
Once the filter function is working, I assume the next step is to simply use the reduce function, then compose them together. ( I could be way off off, however).
I am quite new to programming, any insight is extremely welcome. Thanks!!
const exercise3 = _ => {
const hexes = ["#0000ff", "#f5f5dc", "#cd853f", "#663399", "#ffa500"];
const letter = "r";
const mapper = hex2color;
console.log(map(mapper, hexes)); //blue,beige,peru,rebeccapurple,orange
const filterer = el => contains(hex2color(el), letter);
console.log(filter(filterer, hexes)); //yields nothing, I assume to using the filter wrong with "r".
const reducer = (acc, el) => acc + 1;
const mappedFn = map(mapper);
const filtererFn = filter(filterer);
const reducerFn = reduce(reducer, 0);
const composedFn = compose(reducerFn, filtererFn, mappedFn);
return composedFn(hexes);
};
I am running my code in AWS Lambda(Nodejs). have below code to sort my custom array of objects
let a = [];
let ob1= {"ts": "1582709708.009700"};
let ob2= {"ts": "1582709806.011000"};
let ob3= {"ts": "1582709782.010600"};
let ob4= {"ts": "1582709777.010400"};
let ob5= {"ts": "1582709791.010800"};
a.push(ob1);
a.push(ob2);
a.push(ob3);
a.push(ob4);
a.push(ob5);
a.sort((m1, m2) => {
let m1Ts = moment.unix(m1.ts).utc();
let m2Ts = moment.unix(m2.ts).utc();
return m1Ts.isAfter(m2Ts);
});
the above code returns below result with a runtime of 12.x
[{"ts":"1582709708.009700"},{"ts":"1582709806.011000"},{"ts":"1582709782.010600"},{"ts":"1582709777.010400"},{"ts":"1582709791.010800"}]
and for a runtime of 10.x
[{"ts":"1582709708.009700"},{"ts":"1582709777.010400"},{"ts":"1582709782.010600"},{"ts":"1582709791.010800"},{"ts":"1582709806.011000"}]
The same code gives different results for the sort. Any suggestions?
That is because the algorithm has been changed to Timsort after nodejs11. The order of arguments passed to compare function is changed. You can look into this :https://github.com/nodejs/node/issues/24294
For example:
labelsSetOne = [1,1,1,1,1]
labelsSetTwo = [2,2,2,2,2]
const printLabels = set => {
const set = `labelsSet${set}`
console.log(set)
}
printLabels('one')
One solution is using eval: eval('labelsSet${set}') however, we all know eval is not save or accepted by a lot of people, another way is window['labelsSet${set}'] however, in my case it is not a global variable.
Background
I am learning Ramda and I am trying to use pipe. To this effect I made this simple example that doesn't work:
var getSQLQuery = ( { lang } ) => `My query is ${lang}`;
var addAnd = str => str + " and";
var getMarket = country => data => `${data} my country is ${country}`;
var comp = ( country, queryParams ) => R.pipe(
getSQLQuery( queryParams ),
addAnd,
getMarket( country ),
R.tap( console.log )
)(country, queryParams);
comp("Spain", {lang: "uk"}); //Blows Up!?
The error I get is
First argument to _arity must be a non-negative integer no greater
than ten
I don't know how to fix this. How can I do it?
You can see it live here.
There are many ways one could write such a function. I know your goal is to learn how to use pipe, but let me first show a technique that starts with something similar to your functions:
const getSQLQuery = ( { lang } ) => `My query is ${lang}`;
const getMarket = country => `my country is ${country}`;
const flipAndJoin = pipe(reverse, join(' and '))
const comp = useWith(unapply(flipAndJoin), [getMarket, getSQLQuery])
comp("Spain", {lang: "uk"}); //=> ""My query is uk and my country is Spain"
Now the questions are:
Why does your function not work?
How can you make it work?
How do you make pipe work as desired?
Why does your function not work?
It's simple: pipe takes a number of functions as parameters, with at least one required. The first argument you supply is getSQLQuery( queryParams ), which is the result of calling getSQLQuery with an argument. That is a string, not a function. So when you try to wrap this in pipe, it fails. (The note about 'arity' has to do with the internals of Ramda: it uses the first function to pipe in order to determine how many parameters the resulting function should take.)
How can you make it work?
I gave an answer up above. The answer from MarioF does so with minimal change to your initial functions.
But none of these are as simple as
const comp2 = (country, queryParams) =>
`My query is ${queryParams.lang} and my country is ${country}`
comp2("Spain", {lang: "uk"}); //=> ""My query is uk and my country is Spain"
How do you make pipe work as desired?
You need to realize what pipe does.
Think of a function like this:
const getUpperAddr(userName, collection) {
const configStr = getUserConfig(userName, collection);
const config = JSON.parse(configStr);
const address = prop('address')(config);
const addrLine1 = prop('addrLine1')(address);
const upperAddr = toUpper(addrLine1);
return upperAddr;
}
Forgetting the details, especially of how getUserConfig works, and forgetting any potential errors, we can see one interesting feature of this function: each successive local variable is created by applying a function to the one before. The only exception to this is the first one, which uses the parameters to the function. The result is the final local variable.
pipe is simply a way to make this more declarative, and remove the need for all the local variables (and even the parameter names.) This is equivalent:
const getUpperAddr = pipe(
getUserConfig,
JSON.parse,
prop('address'),
prop('addrLine1'),
toUpper
);
This has the same signature as the above and returns the same result for the same input. If you can write your function in the first format, you can mechanically change to pipe. After a while, this becomes second nature, and you can skip the first step.
It is quite arguable whether this makes the code more readable than just using a single function, but this way you get what you are looking for:
var getSQLQuery = (_, {lang}) => `My query is ${lang}`;
var addAnd = str => str + " and";
var getMarket = country => data => `${data} my country is ${country}`;
var comp = ( country, queryParams ) => R.pipe(
getSQLQuery,
addAnd,
getMarket( country ),
R.tap( console.log )
)(country, queryParams);
comp("Spain", {lang: "uk"});
In answer to the core question "how to use x with multiple arguments", technically you can use R.nthArg, but that doesn't immediately help you pass data down the pipe.
In my opinion, it's better to pass in an array - or use rest parameters. This works:
//Kept as original
var getSQLQuery = ( { lang } ) => `My query is ${lang}`;
var addAnd = str => str + " and";
var getMarket = country => data => `${data} my country is ${country}`;
//only modified this function
const comp = (...args) =>
getMarket(args[0]) (
R.compose(addAnd, getSQLQuery)(args[1])
);
comp("Spain", {lang: "uk"});
Repl here
Though I don't think R.compose really makes that any easier to reason about. Maybe if it's separated out into a named function like this?
const enhanceQuery = R.compose(addAnd, getSQLQuery)
const comp = (...args) =>
getMarket(args[0]) (enhanceQuery(args[1]));
Repl here