## How to Implement LINQ methods in JavaScript - Part 6

blogentry, programming, quicktip, series

## title: How to Implement LINQ methods in JavaScript - Part 6 date: "2018-04-14" banner: ./images/featured-image.jpg published_at: "2018-04-15T01:59:34.000Z" tags: "blogentry, programming, quicktip, series" author: Sung M. Kim

Photo by Baher Khairy on Unsplash I will cover methods for getting subset of sequence.

Here are the methods covered so far.

1. Part 1 〰️ Select, Aggregate, Where, OrderBy (Ascending, Descending)
2. Part 2 〰️ Any, Distinct, Concat, SelectMany
3. Part 3 〰️ Reverse, Zip, Min/Max
4. Part 4 〰️ Union, Intersect, Except
5. Part 5 〰️ Sum, Average, Count
6. Part 6 〰️ First, Last, DefaultIfEmpty, Skip, Take
7. Part 7 〰️ Empty, Repeat, Range
8. Part 8 〰️ All, Contains, SequenceEqual

### 🔴 Overview

[table id=6]

The sample collections used in this part are shown as below.

###### C#
 private static List Orders = new List{ new Order(id: 1, quantity: 40, orderDate: new DateTime(2018, 1,1,1,1,1,1)), new Order(id: 2, quantity: 20, orderDate: new DateTime(2018, 2,2,2,2,2,2)), new Order(id: 3, quantity: 30, orderDate: new DateTime(2018, 3,3,3,3,3,3)), new Order(id: 4, quantity: 10, orderDate: new DateTime(2018, 4,4,4,4,4,4)), new Order(id: 5, quantity: 20, orderDate: new DateTime(2018, 5,5,5,5,5,5)), }; private static Order NullOrder = new Order(-1, 0, DateTime.MinValue);
view raw orders.cs hosted with ❤ by GitHub
###### JavaScript
 const orders = [ { id: 1, quantity: 40, orderDate: new Date(2018, 1, 1, 1, 1, 1) }, { id: 2, quantity: 20, orderDate: new Date(2018, 2, 2, 2, 2, 2) }, { id: 3, quantity: 30, orderDate: new Date(2018, 3, 3, 3, 3, 3) }, { id: 4, quantity: 10, orderDate: new Date(2018, 4, 4, 4, 4, 4) }, { id: 5, quantity: 20, orderDate: new Date(2018, 5, 5, 5, 5, 5) } ]; const nullOrder = { id: -1, quantity: 0, orderDate: new Date(-8640000000000000) };
view raw orders.js hosted with ❤ by GitHub

### 🔴 Examples

##### 🔸 First/FirstOrDefault
 private static void FirsDemo(List orders) { var firstOrderAfterMarch = orders.First(order => order.OrderDate >= march); PrintHeaderFooter("First order after March", () => PrintOrder(firstOrderAfterMarch, indentBy), indentBy); var firstOrderAfterSeptember = orders.FirstOrDefault(order => order.OrderDate >= september); PrintHeaderFooter("First or Default order after September", () => PrintOrder(firstOrderAfterSeptember, indentBy), indentBy); }
view raw FirsDemo.cs hosted with ❤ by GitHub
 Array.prototype.first = function(propertySelector = obj => obj) { return this.filter(propertySelector)[0]; }; function firstDemo(orders) { const firstOrderAfterMarch = orders.first(order => order.orderDate >= march); printHeaderFooter( "First order after March", () => printOrder(firstOrderAfterMarch, indentBy), indentBy ); const firstOrderAfterSeptember = orders.first(order => order.OrderDate >= september) || null; printHeaderFooter( "First or Default order after September", () => printOrder(firstOrderAfterSeptember, indentBy), indentBy ); }
view raw firstDemo.js hosted with ❤ by GitHub
###### Results
 // C# ==================== First/FirstOrDefault DEMO - Get First Order ==================== ==================== First order after March ==================== Order ID: 3, Quantity: 30, Order Date: 03 Mar 2018 03:03 AM pst ==================== First or Default order after September ==================== // JS ==================== Filter (LINQ 'First/FirstOrDefault' Equivalent) DEMO - Get First Order ==================== ==================== First order after March ==================== Order ID: 3, Quantity: 30, Order Date: Tue Apr 03 2018 03:03:03 GMT-0400 (Eastern Daylight Time) ==================== First or Default order after September ====================

I've just used "first" in JavaScript to implement "First/FirstOrDefault". JavaScript is dynamically typed so it wouldn't know what default value is unless you specify unlike in C#.

##### 🔸 Last/LastOrDefault
 private static void LastDemo(List orders) { var lastOrderAfterMarch = orders.Last(order => order.OrderDate >= march); PrintHeaderFooter("Last order after March", () => PrintOrder(lastOrderAfterMarch, indentBy), indentBy); var LastOrderAfterSeptember = orders.LastOrDefault(order => order.OrderDate >= september); PrintHeaderFooter("Last or Default order after September", () => PrintOrder(LastOrderAfterSeptember, indentBy), indentBy); }
view raw LastDemo.cs hosted with ❤ by GitHub
 Array.prototype.last = function(propertySelector = obj => obj) { const filtered = this.filter(propertySelector); return filtered[filtered.length - 1]; }; function lastDemo(orders) { const lastOrderAfterMarch = orders.last(order => order.orderDate >= march); printHeaderFooter( "Last order after March", () => printOrder(lastOrderAfterMarch, indentBy), indentBy ); const lastOrderAfterSeptember = orders.last(order => order.orderDate >= september) || null; printHeaderFooter( "Last or Default order after September", () => printOrder(lastOrderAfterSeptember, indentBy), indentBy ); }
view raw lastDemo.js hosted with ❤ by GitHub
###### Results
 // C# ==================== Last/LastOrDefault DEMO - Get Last Order ==================== ==================== Last order after March ==================== Order ID: 5, Quantity: 20, Order Date: 05 May 2018 05:05 AM pst ==================== Last or Default order after September ==================== // JS ==================== Filter (LINQ 'Last/LastOrDefault' Equivalent) DEMO - Get Last Order ==================== ==================== Last order after March ==================== Order ID: 5, Quantity: 20, Order Date: Tue Jun 05 2018 05:05:05 GMT-0400 (Eastern Daylight Time) ==================== Last or Default order after September ====================

Same as "first", I used "last" in JavaScript to implement both "Last/LastOrDefault"

##### 🔸 DefaultIfEmpty
 private static void DefaultIfEmptyDemo(List orders) { var ordersAfterSeptember = orders.Where(order => order.OrderDate >= september).DefaultIfEmpty(NullOrder); PrintOrders(ordersAfterSeptember); }
 function defaultIfEmptyDemo(orders) { const filteredOrders = orders.filter(order => order.OrderDate >= september); const ordersAfterSeptember = filteredOrders.length === 0 ? [nullOrder] : filteredOrders; printOrders(ordersAfterSeptember); }
###### Results
 // C# ==================== DefaultIfEmpty DEMO - Get Order or Default if Empty ==================== Order ID: -1, Quantity: 0, Order Date: 01 Jan 0001 12:00 AM pst // JS ==================== DefaultIfEmpty DEMO - Get Order or Default if Empty ==================== Order ID: -1, Quantity: 0, Order Date: Mon Apr 19 -271821 20:00:00 GMT-0400 (Eastern Daylight Time)

In JavaScript, filter returns an array of size 0 if no record is returned. So I am checking for the size and return nullOrder if the length is 0.

##### 🔸 Skip/SkipWhile
 private static void SkipDemo(List orders) { var lastTwoOrders1 = orders.Skip(orders.Count - 2); PrintHeaderFooter("Last Two Orders - Skip", () => PrintOrders(lastTwoOrders1, indentBy), indentBy); var lastTwoOrders2 = orders.SkipWhile((order, index) => index < orders.Count - 2); PrintHeaderFooter("Last Two Orders - SkipWhile", () => PrintOrders(lastTwoOrders2, indentBy), indentBy); }
view raw SkipDemo.cs hosted with ❤ by GitHub
 Array.prototype.skip = function(count) { return this.filter((_, i) => i >= count); }; Array.prototype.skipWhile = function(predicate) { return this.filter((_, i) => !predicate(_, i)); }; function skipDemo(orders) { const lastTwoOrders1 = orders.skip(orders.length - 2); printHeaderFooter( "Last Two Orders - Skip", () => printOrders(lastTwoOrders1, indentBy), indentBy ); const lastTwoOrders2 = orders.skipWhile( (order, index) => index < orders.length - 2 ); printHeaderFooter( "Last Two Orders - SkipWhile", () => printOrders(lastTwoOrders2, indentBy), indentBy ); }
view raw skipDemo.js hosted with ❤ by GitHub
###### Results
 // C# ==================== Skip/SkipWhile DEMO - Skip Orders ==================== ==================== Last Two Orders - Skip ==================== Order ID: 4, Quantity: 10, Order Date: 04 Apr 2018 04:04 AM pst Order ID: 5, Quantity: 20, Order Date: 05 May 2018 05:05 AM pst ==================== Last Two Orders - SkipWhile ==================== Order ID: 4, Quantity: 10, Order Date: 04 Apr 2018 04:04 AM pst Order ID: 5, Quantity: 20, Order Date: 05 May 2018 05:05 AM pst // JS ==================== Skip/SkipWhile DEMO - Skip Orders ==================== ==================== Last Two Orders - Skip ==================== Order ID: 4, Quantity: 10, Order Date: Fri May 04 2018 04:04:04 GMT-0400 (Eastern Daylight Time) Order ID: 5, Quantity: 20, Order Date: Tue Jun 05 2018 05:05:05 GMT-0400 (Eastern Daylight Time) ==================== Last Two Orders - SkipWhile ==================== Order ID: 4, Quantity: 10, Order Date: Fri May 04 2018 04:04:04 GMT-0400 (Eastern Daylight Time) Order ID: 5, Quantity: 20, Order Date: Tue Jun 05 2018 05:05:05 GMT-0400 (Eastern Daylight Time)
view raw Skip result hosted with ❤ by GitHub

The callback in Array.prototype.filter also has an access to current index being process. So the implementation for skip simply filters out records below the given count while skipWhile filters out records that do not match the predicate.

##### 🔸 Take/TakeWhile
 private static void TakeDemo(List orders) { var firstTwoOrders1 = orders.Take(2); PrintHeaderFooter("First Two Orders - Take", () => PrintOrders(firstTwoOrders1, indentBy), indentBy); var firstTwoOrders2 = orders.TakeWhile((order, index) => index <= 1); PrintHeaderFooter("First Two Orders - TakeWhile", () => PrintOrders(firstTwoOrders2, indentBy), indentBy); }
view raw TakeDemo.cs hosted with ❤ by GitHub
 Array.prototype.take = function(count) { return this.filter((_, i) => i < count); }; Array.prototype.takeWhile = function(predicate) { return this.filter((_, i) => predicate(_, i)); }; function takeDemo(orders) { const firstTwoOrders1 = orders.take(2); printHeaderFooter( "First Two Orders - Take", () => printOrders(firstTwoOrders1, indentBy), indentBy ); const firstTwoOrders2 = orders.takeWhile((order, index) => index <= 1); printHeaderFooter( "First Two Orders - TakeWhile", () => printOrders(firstTwoOrders2, indentBy), indentBy ); }
view raw takeDemo.js hosted with ❤ by GitHub
###### Results
 // C# ==================== Take/TakeWhile DEMO - Take Orders ==================== ==================== First Two Orders - Take ==================== Order ID: 1, Quantity: 40, Order Date: 01 Jan 2018 01:01 AM pst Order ID: 2, Quantity: 20, Order Date: 02 Feb 2018 02:02 AM pst ==================== First Two Orders - TakeWhile ==================== Order ID: 1, Quantity: 40, Order Date: 01 Jan 2018 01:01 AM pst Order ID: 2, Quantity: 20, Order Date: 02 Feb 2018 02:02 AM pst // JS ==================== Take/TakeWhile DEMO - Take Orders ==================== ==================== First Two Orders - Take ==================== Order ID: 1, Quantity: 40, Order Date: Thu Feb 01 2018 01:01:01 GMT-0500 (Eastern Standard Time) Order ID: 2, Quantity: 20, Order Date: Fri Mar 02 2018 02:02:02 GMT-0500 (Eastern Standard Time) ==================== First Two Orders - TakeWhile ==================== Order ID: 1, Quantity: 40, Order Date: Thu Feb 01 2018 01:01:01 GMT-0500 (Eastern Standard Time) Order ID: 2, Quantity: 20, Order Date: Fri Mar 02 2018 02:02:02 GMT-0500 (Eastern Standard Time)
view raw gistfile1.txt hosted with ❤ by GitHub

Take is the opposite of skip so the boolean conditions are reversed.

### 🔴 Closing Remark

JavaScript is dynamically typed so returning a "default" value is tricky as a variable type is defined upon initialization. I've skipped implementing "OrDefault" methods for that reason.

Please let me know should you find any errors or improvements I can make to the codes.

The full source code and instructions on how to run them are on GitHub.