LINQ-kenderens guide til JavaScript

Som udvikler i .NET verdenen med LINQ som first class citizen, kan man ved første øjekast på JavaScript mangle nogle operationer. Der er endda en række biblioteker der implementerer disse, men er man bare ude i en get-the-job-done-situation er de mest brugte funktioner lige ved hånden. (Leder man efter aspekter som Lazy-evaluering eller observables er henholdsvis linq.js og RxJS bedre bud.)

Jeg vil her liste de mest almindelige udtryk og deres JavaScript ækvivalenter cheat-sheet-style. Bemærk at jeg bruger Lambdaudtryk i JavaScript for at få koden lidt mere koncis men hvis du ikke har adgang til dette er det bare at erstatte udtryk som fx:

(data) => {}

med

function(data) {}

Alle operationer afvikles mod dette eksempel:

var persons = [
    { firstname: 'Peter', lastname: 'Jensen', type: 'Person', age: 30 },
    { firstname: 'Anne', lastname: 'Jensen', type: 'Person', age: 50  },
    { firstname: 'Kurt', lastname: 'Hansen', type: 'Person', age: 40  }
];

Bemærk at nogle af operationerne modificerer det oprindelige array, hvis man ikke ønsker det kan man blot klone den med:

persons.slice(0);

Hver operation er her navngivet efter funktionens navn i LINQ:

All

C#
	var result = persons.All(person => person.type == "Person");
JavaScript
	var result = persons.filter(person => person.type == 'Person').length == persons.length;

Concat

C#
	var result = persons.Concat(persons);
JavaScript
	var result = persons.concat(persons);

Count

C#
	var result = persons.Count();
JavaScript
	var result = persons.length;

Distinct

C#
	var lastnames = persons.Select(person => person.lastname);
    var result = lastnames.Distinct();
	
JavaScript
	var lastnames = persons.map(person => person.lastname);
    var result = lastnames.filter((value, index) => lastnames.indexOf(value) == index);

Empty

C#
	var result = Enumerable.Empty<dynamic>();
JavaScript
	var result = [];

First

C#
	var result = persons.First();
JavaScript
	var result = persons[0];
    if (!result) throw new Error('Expected at least one element to take first')

FirstOrDefault

C#
	var result = persons.FirstOrDefault();
JavaScript
	var result = persons[0];

ForEach

C#
	var fullnames = new List<string>();
    persons.ForEach(person => fullnames.Add(person.firstname + " " + person.lastname));
JavaScript
var fullnames = [];
persons.forEach(person => fullnames.push(person.firstname + ' ' + person.lastname))

GroupBy

C#
	var result = persons.GroupBy(person => person.lastname);
JavaScript
	var result = persons.reduce((previous, person) => {
		(previous[person.lastname] = previous[person.lastname] || []).push(person);
    	return previous;
	}, []);

IndexOf

C#
	var result = persons.IndexOf(persons[2]);
JavaScript
	var result = persons.indexOf(persons[2]);

Last

C#
	var result = persons.Last();
JavaScript
	var result = persons[persons.length-1];
    if (!result) throw new Error('Expected at least one element to take last')

LastOrDefault

C#
	var result = persons.LastOrDefault();
JavaScript
	var result = persons[persons.length-1];

OrderBy

C#
	var result = persons.OrderBy(person => person.firstname);
JavaScript
	persons.sort((person1, person2) => person1.firstname.localeCompare(person2.firstname));

OrderByDescending

C#
	var result = persons.OrderByDescending(person => person.firstname);
JavaScript
	persons.sort((person1, person2) => person2.firstname.localeCompare(person1.firstname));

Reverse

C#
	persons.Reverse();
JavaScript
	var result = persons.reverse();

Select

C#
	var result = persons.Select(person => new {fullname = person.firstname + " " + person.lastname});
JavaScript
	var result = persons.map(person => ({ fullname: person.firstname + ' ' + person.lastname }) );

Single

C#
	var result = persons.Single(person => person.firstname == "Peter");
JavaScript
	var onePerson = persons.filter(person => person.firstname == "Peter");
    if (onePerson.length != 1) throw new Error('Expected at excactly one element to take single')
    var result = onePerson[0];

Skip

C#
	var result = persons.Skip(2);
JavaScript
	var result = persons.slice(2, persons.length); 

Take

C#
	var result = persons.Take(2);
JavaScript
	var result = persons.slice(0, 2);

Where

C#
	var result = persons.Where(person => person.lastname == "Jensen");
JavaScript
	var result = persons.filter(person => person.lastname == 'Jensen');

Så tydeligvis behøver man ikke et bibliotek hvis man blot skal bruge de simple operationer. Ovenstående kode med tests er tilgængelig på GitHub.

This post is also available in English at Complexitymaze.com.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *