Today was my first day working with JavaScript and I tried to implement some Linq-like (C#) functions as extension methods.
I'm pretty new to JavaScript and wanted to ask you for checking my functions and tell me, whether they're good and really usable in productive applications. Or maybe, what I could do better. I don't know whether there is already a library for this; it's primarily for learning purposes.
Array.prototype.where = function * (predicate){
for(var i=0; i < this.length; i++){
if (predicate(this[i])) yield this[i];
}
}
Array.prototype.all = function (predicate){
for(var i=0; i < this.length; i++){
if (!predicate(this[i])) return false;
}
return true;
}
Array.prototype.any = function (predicate){
if (predicate == null) return this.length >0;
for(var i=0; i < this.length; i++){
if (predicate(this[i])) return true;
}
return false;
}
Array.prototype.select = function * (predicate){
for(var i=0; i < this.length; i++){
yield predicate(this[i], i);
}
}
Array.prototype.groupby = function (predicate){
var result = {};
for(var i=0; i < this.length; i++){
var key = predicate(this[i]);
if (result[key] == null)
result[key] = Array();
result[key].push(this[i]);
}
return result;
}
Array.prototype.foreach = function (predicate){
for(var i=0; i < this.length; i++){
predicate(this[i]);
}
}
Array.prototype.first_or_default = function (predicate){
if (predicate == null){
return this.length > 0 ? this[0] : null;
}
for(var i=0; i < this.length; i++){
if (predicate(this[i]))
return this[i];
}
return null;
}
Array.prototype.last_or_default = function (predicate){
return this.reverse().first_or_default();
}
Array.prototype.count = function (predicate){
var count = this.length;
if (predicate == null) return count;
for(var i=0; i < this.length; i++){
if (!predicate(this[i])) count-=1;
}
return count;
}
Array.prototype.distinct = function * (predicate){
var already_yielded = []
var has_predicate = predicate != null;
for(var i=0; i < this.length; i++){
var current_element = this[i];
if (!has_predicate){
if (already_yielded.indexOf(current_element) >= 0) continue;
already_yielded.push(current_element);
}else{
if (already_yielded.indexOf(predicate(current_element)) >= 0) continue;
already_yielded.push(predicate(current_element));
}
yield current_element;
}
}
-
\$\begingroup\$ I wrote a LINQ in Javascript library at github.com/Siderite/LInQer. I am looking for feedback on how to improve it. As for your code, it works, but it could use some optimizations. For example the groupby function reads the item in the dictionary object twice each item. Also result[key] is only incidentally equal to null, in fact it is undefined and it is more efficient to use === and compare the value and the type at the same time. Then you have functions like last or default which reverses the entire array and returns the first item instead of actually return the last item... \$\endgroup\$Siderite Zackwehdex– Siderite Zackwehdex2020年01月27日 12:29:45 +00:00Commented Jan 27, 2020 at 12:29
1 Answer 1
This might not really be an answer, but I suggest you to check out linq.js. So yes, there is already an implementation of this and you can look at the code to compare and it will help the "learning purposes" you're aiming for.
Example implementation of any
:
// Overload:function()
// Overload:function(predicate)
Enumerable.prototype.any = function (predicate) {
predicate = Utils.createLambda(predicate);
var enumerator = this.getEnumerator();
try {
if (arguments.length == 0) return enumerator.moveNext(); // case:function()
while (enumerator.moveNext()) // case:function(predicate)
{
if (predicate(enumerator.current())) return true;
}
return false;
}
finally {
Utils.dispose(enumerator);
}
};
I personally don't have the required experience in JavaScript to give you my opinion on your implementation. Good luck !
-
\$\begingroup\$ ah pretty nice. didn't know about linq.js and didn't know about that enumerator-thing. :) thanks for that post! \$\endgroup\$Matthias Burger– Matthias Burger2017年01月16日 17:12:32 +00:00Commented Jan 16, 2017 at 17:12
-
\$\begingroup\$ So for education and the hints I mark this answer as accepted. Linq.js seems to do exactly what I want to do and for reference of best practice this is the perfect answer. \$\endgroup\$Matthias Burger– Matthias Burger2017年01月16日 22:42:22 +00:00Commented Jan 16, 2017 at 22:42
-
\$\begingroup\$ Linq.js was nice find for me a while back coming from the C# world. Awesome once you get the syntax down. \$\endgroup\$jaredbaszler– jaredbaszler2017年01月19日 23:15:15 +00:00Commented Jan 19, 2017 at 23:15