Equivalent to LINQ's Enumerable.First(predicate)
JavascriptArraysnode.jsLinqFilterJavascript Problem Overview
In C#, we have Enumerable.First(predicate)
. Given this JavaScript code:
function process() {
var firstMatch = ['a', 'b', 'c'].filter(function(e) {
return applyConditions(e);
}).shift();
if(!firstMatch) {
return;
}
// do something else
}
function applyConditions(element) {
var min = 97;
var max = 122;
var random = Math.floor(Math.random() * (max - min + 1) + min);
return element === String.fromCharCode(random);
}
other than forEach
, using loop, using multiple or operators or implicitly calling some(predicate)
, is there a smarter way of finding the firstMatch
? Preferably a JavaScript function (something like filterFirst(pedicate)
) which short-circuits on first match resembling C#'s Enumerable.First()
implementation?
FWIW, I am targeting node.js / io.js runtimes.
Javascript Solutions
Solution 1 - Javascript
No need to reinvent the wheel, the correct way to do it is to use .find
:
var firstMatch = ['a', 'b', 'c'].find(applyConditions);
If you're using a browser that does not support .find
you can polyfill it
Solution 2 - Javascript
LINQ
users call first
and firstOrDefault
a lot with no predicate, which is not possible with find
. So,
first() {
var firstOrDefault = this.firstOrDefault();
if(firstOrDefault !== undefined)
return firstOrDefault;
else
throw new Error('No element satisfies the condition in predicate.');
}
firstOrDefault() {
return this.find(o => true);
}
Solution 3 - Javascript
You could emulate this in the case where you want to return the first truthy value with reduce
.
['a', 'b', 'c'].reduce(function(prev, curr) {
return prev || predicate(curr) && curr;
}, false);
edit: made more terse with @BenjaminGruenbaum suggestion
Solution 4 - Javascript
There are a few packages:
linq.js - LINQ for JavaScript
https://github.com/mihaifm/linq/
npm install linq
> This is a JavaScript implementation of the .NET LINQ library. > > It contains all the original .NET methods plus a few additions. > > Written in pure JavaScript with no dependencies.
https://www.npmjs.com/package/linq-to-typescript
Implementation of LINQ for TypeScript
await from([bing, google, quackQuackGo])
.asParallel()
.selectAsync(downloadHtml)
.select(getTitle)
.toArray()
Solution 5 - Javascript
If you want to create something reusable: Define a predicate type first
declare global {
type predicate<T> = (arg: T) => boolean;
}
Then define the prototype function on array:
if (!Array.prototype.First) {
Array.prototype.First = function <T>(condition: predicate<T>): T {
let matchingItems: T[] = this.filter((item: T) => {
if (condition(item))
return item;
});
if (matchingItems === null || matchingItems === undefined || matchingItems.length === 0) {
throw Error('Invalid operation. No items found.');
}
return matchingItems[0];
}
}
Now you can call the method 'First' on your array and pass in the predicate. Also supported here is any function return a boolean such as your function 'applyConditions'.