Overrides the base array type adding in Linq-style commands.
Current commands are:
- Where
- Join
- Select
- FirstOrDefault
- LastOrDefault
- Max
- Min
- Count
- Sum
- OrderBy
- OrderByDescending
- Skip
- Take
- IdenticalTo
- Distinct
- GroupBy
More commands to come soon!
Please note: There are some limitations to the number of parameters you can Order By or Group By, for example, the GroupBy method doesn't yet allow grouping by multiple parameters (unless you combine them into a string). For the next major build I will be looking into deep comparisons of objects.
I hope you find this useful, whoever you are.
Just install the package
npm install linq4typescript
and use as:
import 'linq4typescript';
Angular tip! If you use Angular (2+) just import into your base AppModule and the functions will be accessible throughout the module.
Here is a set-up with some example data which we will use for the following demonstrations:
class HumanName{
public PersonID: number;
public Name: string;
};
class BirthDate{
public PersonID: number;
public DOB: Date;
public Candles: number;
};
const HumanNames: HumanName[] = [
{ PersonID: 1, Name: 'Daniel' },
{ PersonID: 2, Name: 'James' },
{ PersonID: 3, Name: 'Lee' }
];
const Birthdates: BirthDate[] = [
{ PersonID : 1, DOB : new Date(1991,1,1), Candles: 29 },
{ PersonID : 2, DOB : new Date(1996,1,1), Candles: 24 },
{ PersonID : 3, DOB : new Date(1999,2,1), Candles: 21 }
];
function GetNamesBornAfter1995() : string[]
{
return Birthdates
.Join(HumanNames, (dob, name) => name.PersonID == dob.PersonID, (dob, name) => ({ Name: name, Dob: dob }))
.Where(x => x.Dob.DOB > new Date(1995,1))
.Select(x => x.Name.Name);
}
This returns ['James','Lee']
Sums over a property defined by the selector 'fn'.
function GetSumOfCandles() : number
{
return Birthdates.Sum(bd => bd.Candles);
}
This returns 74.
If the array's type is numeric, you can pass in the selector x => x
and it will sum over the values in the numeric array.
Counts the number of elements. Does the same as the length property.
function CountHumanNames() : number
{
return HumanNames.Count();
}
This returns 3.
Takes a condition as a function parameter to filter the elements.
function WhereCandlesLessThan25() : BirthDate[]
{
return Birthdates.Where(bd => bd.Candles < 25);
}
Same as Where
but only applies the filter condition if the supplied check is correct.
function ShouldIApplyTheCheck(yesorno: boolean) : BirthDate[]
{
return Birthdates.WhereIf(yesorno, bd => bd.Candles < 25);
}
If yesorno = true
it will return objects which have Candles < 25
otherwise it will return the whole original array, unfiltered.
Allows the type to be changed such that, for example, a property of the original object type is selected.
function GetFirstLetterOfNames() : string[]
{
return HumanNames.Select(hn => hn.substring(0,1));
}
This returns ['D','J','L']
Performs an 'inner join' of two arrays.
A join between two arrays requires three parameters.
- The array you want to join in with this array
- The condition on which you want to join the two arrays, i.e. by using a shared ID.
- The output object which will define the type of the new array.
function GetNameAndBirthdateAsText() : string[]
{
return Birthdates
.Join(
/* Array to join with Birthdates */
HumanNames,
/* Condition on which to join them */
(dob, name) => name.PersonID == dob.PersonID,
/* defines the result, i.e. 'Daniel 1991-01-01' */
(dob, name) => name.Name + ' ' + dob.DOB.toISOString()
);
}
FirstOrDefault (and LastOrDefault) will return null if the array is empty, unless a different default value is specified.
function GetLastBirthDate()
{
return Birthdates
.Select(bd => bd.DOB)
.LastOrDefault(new Date());
}
The above should return the date '1999-01-01'. If the Birthdates array were empty, it would return today's date.
Beware that this example has no ordering! That brings us on to...
Using these two functions, we only need to pass in a selector function for the property or value which we want to sort by.
If we use OrderBy, it sorts ascending. If we use OrderByDescending, it sorts descending.
function OrderByDateOfBirth()
{
return Birthdates
.OrderBy(bd => bd.DOB);
}
The Max (or Min) function will return the Maximum (or Minimum) value according to the selector function.
function GetMaxBirthDate()
{
/* should return 1999 */
return Birthdates.Max(bd => bd.DOB);
}
function GetMinBirthDate()
{
/* should return 1991 */
return Birthdates.Min(bd => bd.DOB);
}
The Skip function removes the first n values from the array. The Take function returns the first n values from the array.
This could be useful for paging.
(please note, 'pagination' is not a real word, if you look it up 'paging' in the dictionary you'll have what you require)
function GetPageData(pageIndex : number, pageSize: number)
{
return MyData.Skip(pageSize * pageIndex).Take(pageSize);
}
Compares the values in an array and returns true if both arrays have identical values in the same order.
The distinct function will find a set of distinct objects according to the values selected. The return array will have the same return type as the selector.
function GetDistinctDatesAsStrings() : any[]
{
/* compares the ISO Strings of dates and gets distinct values */
return Birthdates.Distinct(bd => bd.DOB.toISOString());
}
Warning! This hasn't been tested yet comparing objects, only base types. It is unlikely to properly compare objects by their properties, though I will look into this soon.
Groups by the key function (parameter 1) and returns the keys with their related set
function GroupByMonth()
{
return Birthdates.GroupBy(
/* The first parameter is the key to group by */
bd => bd.DOB.getMonth(),
/* The second parameter is the result we want in the return array, i.e. applying an aggregate function */
(month, set)=> set.Sum(bd => bd.Candles));
}
This should return an array of two numbers, the first being the sum of (29 and 24), corresponding to the month 1, the second being 21, corresponding to the month 2.