Is there any way to replace this lodash _.chain code with javascript in modern browsers?

I have this code that uses lodash _.chain. I would like to simplify the code, not use lodash and do it differently.

examObjectives = _.chain(objectives) .where({ 'examId': exam }) .uniq(true, 'id') .map(function (s): any { return { id: s.id, text: s.text, numberAndText: s.numberAndText }; }) .value(); 

Can someone give me some tips on how I can remove the dependency on lodash, _.chain and code, which makes the most of the available javascript features that can now be found in new browsers. Note. I would like to use the built-in filter and map functions and not use any external functions to create examObjectives.

I hope someone can come up with some ideas. I am not very familiar with javascript, so I'm glad to be able to find out.

+6
source share
5 answers

I put some things together and the code is as follows:

 objectives.filter(function (x) { return x.examId == exam; }).reduce(function (accumulator, current) { if (!accumulator.some(function (x) { return x.id == current.id; })) { accumulator.push(current); } return accumulator; }, []).map(function (x) { return { id: x.id, text: x.text, numberAndtext: x.numberAndText } }); 

("uniquifier" inspired by fooobar.com/questions/60444 / ... ).

You can shorten this code by extracting a property comparison with a constant value using the following function:

 function propertyEqualTo(prop, val) { return function (x) { return x[prop] == val; }; } 

and your code will read:

 return objectives.filter(propertyEqualTo('examId', exam)).reduce(function (accumulator, current) { if (!accumulator.some(propertyEqualTo('id', current.id)) { accumulator.push(current); } ... 

Are you sure you need uniq() call here? You match for id , which must be unique from the start. If you could delete this call, your code will be very short.

+6
source

You can start defining regular functions that the last receiver will receive for convenience, for example:

 var map = function(f, xs) { return xs.map(f) } var filter = function(f, xs) { return xs.filter(f) } 

Then you can build the chain using the arguments object:

 var methods = {map: map, filter: filter} var chain = function(xs) { return Object.keys(methods).reduce(function(acc, k) { acc[k] = function() { var as = [].slice.call(arguments) return methods[k].apply(this, as.concat([xs])) } return acc },{}) } 

Now you can do:

 filter(even, map(plus1, [1,2,3])) //=> [2,4] 

As well as:

 chain([1,2,3]).map(plus1).filter(even) //=> [2,4] 

And if the functions were in curry, you can also express it as:

 var chain = compose(filter(even), map(plus1)) chain([1,2,3]) //=> [2,4] 
+6
source

It depends on what you really want to do.

You want to know how to implement the lodash functions that you use with the modern browser API

Use the suggested solutions in this section.

Do you want to remove lodash dependency

If so, I think you want to publish the library without dependencies.

Please note that Underscore and Lodash are under the MIT license , so you can simply copy / paste the functions you need and directly paste them into your distributed / lib / whatever application.

Do you want good performances

Just keep in mind that using a modern browser API is not always a way to achieve better results. Javascript is now very fast (if you are not directly manipulating the DOM, check out ReactJS ), and it is often faster to use efficient JS code than poorly designed native code. Also, not all browser API functions are implemented using native code.

By combining underscore expressions, at each step you create an intermediate array, which leads to increased memory consumption and garbage collection activity. According to the size of your initial array, this may affect the performance of your application, and it would be better to use imperative code.

The modern technique of processing these intermediate distributions of arrays while maintaining the style of functional programming is to use converters . There are currently two main implementations of JS:

This can be considered as premature optimization for small arrays, but in fact, converters are not very complex and do not represent such complexity. If you want to feel at home, you can use underscore-tranceducers , which offers an API very similar to Underscore.

+1
source
 objectives = [{ id: 1, text: 'hello', numberAndText: 'sdfafaadsf', examId: 'exam' }, { id: 2, text: 'hello', numberAndText: 'sdfafaadsf', examId: 'exam2' }]; var result = objectives .filter(function(item) { return item['examId'] === 'exam'; }) .map(function(item) { return { id: item.id, text: item.text, numberAndText: item.numberAndText }; }) .reduce(function(prev, curr) { var ids = prev.map(function(item) { return item.id; }); if (ids.indexOf(curr.id) < 0) { prev.push(curr); } return prev; }, []); 

with a smaller filter map, you can simply achieve this with vanilla js

0
source

All of the following functions of one trick were taken from mofun.js , which I wrote as lodash, but completely modular (no internal method-dependent), and it made full use of its own methods.

 // mofun.js-provided stock utility stand-alone functions: function where(o,_,__){var t=this;return Object.keys(t).every(function(k,_,__){return o[k]===t[k];});} function extract(o,_,__){return o[""+this];} function extractObject(o,_,__){var o2={};this.forEach(function(t,_,__){return o2[t]=o[t];});return o2;} function groupBy(r,s){var ret={};r.forEach(function(a,_,__){var k=a[s],b=ret[k]||(ret[k]=[]);b.push(a);});return ret;} function obVals(o){var t=[],n=0;for(var r in o)o.hasOwnProperty(r)&&(t[n++]=o[r]);return t;} // begin custom code: obVals( // temp object back into array of values groupBy( // group array of objects into a grouped temp object of arrays objectives.filter(where, { 'examId': exam }) // only objects with the proper examId , "id") // groupBy using "id" peoperty of each object ) .map(extract, 0) //take first value of each group array to get unique ids among result objects .map(extractObject, ["id", "text", "numberAndText"]) // extract some properties into a blank object 

the code remains the same as lodash, with the exception of the part on finding unique objects based on a sub-property (instead of comparing the whole object), which I performed by grouping on this property, and then plucking the first element from each group; adjust if necessary.

-1
source

Source: https://habr.com/ru/post/977589/


All Articles