Equivalent to LINQ's Enumerable.First(predicate)

JavascriptArraysnode.jsLinqFilter

Javascript 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()

older https://www.npmjs.com/package/linq-typescript

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'.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionvulcan ravenView Question on Stackoverflow
Solution 1 - JavascriptBenjamin GruenbaumView Answer on Stackoverflow
Solution 2 - JavascripttoddmoView Answer on Stackoverflow
Solution 3 - JavascriptxzyferView Answer on Stackoverflow
Solution 4 - JavascriptMichael FreidgeimView Answer on Stackoverflow
Solution 5 - JavascriptTore AurstadView Answer on Stackoverflow