2018-03-10

How to Implement LINQ methods in JavaScript - Part 3

blogentry, programming, quicktip, series

banner

Photo by Chris Lawton on Unsplash

This is the 3rd part of the series. 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

Here are the methods covered.

[table id=3 /]

And I will try to stick to using Vanilla JS as I have so far.

The sample collection used in this part is the same as all previous ones but I will list again.

C#

https://gist.github.com/dance2die/91eccd44af4248a07ca031c7cb97c1d5

JavaScript

https://gist.github.com/dance2die/8ddcdfd02c4dc710d16cc71875a748c5

OK, now let's dive into some examples 👍.

🔴 Examples

🔸 Reverse

Ah yes. Yet again, there is another JavaScript method named same as in LINQ, reverse. ⚡ NOTE ⚡: Both in LINQ & JavaScript, reverse has a side effect; it alters current collection and doesn't return a new array.

https://gist.github.com/dance2die/b1d35b898bb62f577854b10571fc81ee

https://gist.github.com/dance2die/30d8fa3f3c240c8cbafcf2c16ad2d161

Results

https://gist.github.com/dance2die/164aa4763dd5a74aacbcc50398cce795

Reverse is different from OrderByDescending that you don't specify which element to reverse with. It simply reverses the  current sequence in opposite order.

So to make the demo show how reverse works, I flipped first half and last half of the orders and reversed the list.

And now let's move onto the next example, Zip, which is you might use seldom.

🔸 Zip

There is no one-to-one equivalence in JavaScript but you can emulate one. Note that Lodash has zipWith method which works the same as the LINQ version (Maybe I will write LINQ -> Lodash equivalent methods as a next series 😉).

https://gist.github.com/dance2die/346e92a6beaf551c8120652d6351d3e7

https://gist.github.com/dance2die/36a0b9f37a5d98d908b886522597972a

Results

https://gist.github.com/dance2die/fe2e148190c62aadca83e65d80f64540

As Zip returns one element from each collection in order, we can emulate the functionality in JavaScript with map, which accepts a callback with an index. We can simply retrieve the matching second collection's item (const text = orderNumbersInText[index]) with the callback's index. Refer to a simpler case on this StackOverflow answer.

🔸 Min/Max

Although Lodash has a similar methods, minBy and maxBy that works the same way as LINQ, I will show you a way to implement it using Math.min and Math.max. (I've combined two methods since both min and max are called the same way)

https://gist.github.com/dance2die/4c00edfc21e4e6d1122fb37ae90eb26b

https://gist.github.com/dance2die/07ef47f94bac0fc2ffa5f2f4b416e95c

Results

https://gist.github.com/dance2die/1ffc1636e85a872de0078e35ccf182ee

You can use "Math.min/max" functions to emulate LINQ versions of Min/Max.

Notice that spread syntax (...orders) is used within Math.min/max functions because those functions accept a list of values, not an array, So the array destructuring is required.

If you use "min/max" frequently or make it look just like the LINQ version, you can simply extend the Array prototype as shown below.

https://gist.github.com/dance2die/dedfbb43f3b0b32820ac960b0b4a4533

Now the it looks the same as the LINQ version.

🔴 Closing Remark

I've chosen some random LINQ methods this time but I will show you how to convert LINQ methods dealing with set operations (union, intersect, etc) in JavaScript.

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