Skip to content

Commit

Permalink
Array Pipes
Browse files Browse the repository at this point in the history
  • Loading branch information
danrevah committed Nov 26, 2016
1 parent 210d319 commit e33f5e6
Show file tree
Hide file tree
Showing 19 changed files with 321 additions and 27 deletions.
94 changes: 94 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
- [union](#union)
- [unique](#unique)
- [without](#without)
- [pluck](#pluck)
- [shuffle](#shuffle)
- [every](#every)
- [some](#some)
- [Math](#Math)
- [min](#min)
- [max](#max)
Expand Down Expand Up @@ -332,6 +336,96 @@ this.items = [1, 2, 3, 1, 2, 3];
<li *ngFor="let item of items | without: [1,3]"> <-- Array: [2, 2] -->
```

### pluck

Returns array of properties values

Api: `array | pluck: propertyName`

```typescript
this.items = [
{
a: 1,
b: {
c: 4
}
},
{
a: 2,
b: {
c: 5
}
},
{
a: 3,
b: {
c: 6
}
},
];
```

```html
<li *ngFor="let item of items | pluck: 'a'"> <-- Array: [1, 2, 3] -->
<li *ngFor="let item of items | pluck: 'b.c'"> <-- Array: [4, 5, 6] -->
```

### shuffle

Returns randomly shuffled array

Api: `array | shuffle`

```typescript
this.items = [1, 2, 3, 4, 5, 6];
```

```html
<li *ngFor="let item of items | shuffle"> <-- Array: [4, 1, 6, 2, 5, 3] -->
```

### every

Returns boolean value if every elements of the array fits the predicate

Api: `array | every: predicate`

```typescript
this.itemsOne = [1, 1, 1];
this.itemsTwo = [1, 1, 2];
this.itemsThree = [2, 2, 2];
this.predicate = (value: any, index: number, array: any[]): boolean => {
return value === 1;
};
```

```html
<p>{{ itemsOne | every: predicate }}</p> <-- Output: "true" -->
<p>{{ itemsTwo | every: predicate }}</p> <-- Output: "false" -->
<p>{{ itemsThree | every: predicate }}</p> <-- Output: "false" -->
```

### some

Returns boolean value if some elements of the array fits the predicate

Api: `array | some: predicate`

```typescript
this.itemsOne = [1, 1, 1];
this.itemsTwo = [1, 1, 2];
this.itemsThree = [2, 2, 2];
this.predicate = (value: any, index: number, array: any[]): boolean => {
return value === 1;
};
```

```html
<p>{{ itemsOne | some: predicate }}</p> <-- Output: "true" -->
<p>{{ itemsTwo | some: predicate }}</p> <-- Output: "true" -->
<p>{{ itemsThree | some: predicate }}</p> <-- Output: "false" -->
```

## Math

### min
Expand Down
5 changes: 3 additions & 2 deletions bin/app/pipes/array/array.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import { DiffPipe } from "./diff";
export declare const ARRAY_PIPES: typeof DiffPipe[];
import { DiffPipe } from './diff';
import { EveryPipe } from './every';
export declare const ARRAY_PIPES: (typeof DiffPipe | typeof EveryPipe)[];
27 changes: 16 additions & 11 deletions bin/app/pipes/array/array.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/app/pipes/array/array.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bin/app/pipes/utils/utils.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export declare function isUndefined(value: any): boolean;
export declare function isNumber(value: any): boolean;
export declare function isNumberFinite(value: any): boolean;
export declare function extractProperty(obj: any, map: string): any;
12 changes: 12 additions & 0 deletions bin/app/pipes/utils/utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/app/pipes/utils/utils.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng2-pipes",
"version": "0.4.0",
"version": "0.4.1",
"author": "Dan Revah",
"description": "Useful angular2 pipes",
"license": "MIT",
Expand Down
27 changes: 16 additions & 11 deletions src/app/pipes/array/array.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import {DiffPipe} from "./diff";
import {InitialPipe} from "./initial";
import {FlattenPipe} from "./flatten";
import {IntersectionPipe} from "./intersection";
import {ReversePipe} from "./reverse";
import {TailPipe} from "./tail";
import {TrurthifyPipe} from "./truthify";
import {UnionPipe} from "./union";
import {UniquePipe} from "./unique";
import {WithoutPipe} from "./without";
import {DiffPipe} from './diff';
import {InitialPipe} from './initial';
import {FlattenPipe} from './flatten';
import {IntersectionPipe} from './intersection';
import {ReversePipe} from './reverse';
import {TailPipe} from './tail';
import {TrurthifyPipe} from './truthify';
import {UnionPipe} from './union';
import {UniquePipe} from './unique';
import {WithoutPipe} from './without';
import {PluckPipe} from './pluck';
import {ShufflePipe} from './shuffle';
import {EveryPipe} from './every';
import {SomePipe} from './some';

export const ARRAY_PIPES = [
DiffPipe, FlattenPipe, InitialPipe, IntersectionPipe, ReversePipe, TailPipe,
TrurthifyPipe, UnionPipe, UniquePipe, WithoutPipe
TrurthifyPipe, UnionPipe, UniquePipe, WithoutPipe, PluckPipe, ShufflePipe,
EveryPipe, SomePipe
];
18 changes: 18 additions & 0 deletions src/app/pipes/array/every.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {EveryPipe} from './every';
import {isNumber, isUndefined} from '../utils/utils';

describe('EveryPipe', () => {
let pipe: EveryPipe;

beforeEach(() => {
pipe = new EveryPipe();
});

it('should check if every elements of the array fits the predicate', () => {
expect(pipe.transform([1, 2, 3, 4], isNumber)).toBeTruthy();
expect(pipe.transform([1, 2, 3, 'a'], isNumber)).toBeFalsy();
expect(pipe.transform([1, 2, 3, 4], isUndefined)).toBeFalsy();
expect(pipe.transform([undefined, undefined, 1], isUndefined)).toBeFalsy();
expect(pipe.transform([undefined, undefined], isUndefined)).toBeTruthy();
});
});
11 changes: 11 additions & 0 deletions src/app/pipes/array/every.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {PipeTransform, Pipe, Injectable} from '@angular/core';
import {extractProperty} from '../utils/utils';

@Injectable()
@Pipe({name: 'every'})
export class EveryPipe implements PipeTransform {

transform(arr: any[], predicate: (value: any, index: number, array: any[]) => boolean): boolean {
return Array.isArray(arr) ? arr.every(predicate) : arr;
}
}
18 changes: 18 additions & 0 deletions src/app/pipes/array/pluck.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {PluckPipe} from './pluck';

describe('PluckPipe', () => {
let pipe: PluckPipe;

beforeEach(() => {
pipe = new PluckPipe();
});

it('should return only the properties of the array of object', () => {
const arr = [{foo: 'bar', a: 1, b: {c: 4}},{foo: 'bar2', a: 2, b: {c: 5}}, {foo: 'bar3', a: 3, b: {c: 6}}];
expect(pipe.transform(arr, 'a')).toEqual([1, 2, 3]);
expect(pipe.transform(arr, 'foo')).toEqual(['bar', 'bar2', 'bar3']);
expect(pipe.transform(arr, 'foo.d')).toEqual([undefined, undefined, undefined]);
expect(pipe.transform(arr, 'b.c')).toEqual([4, 5, 6]);
expect(pipe.transform(arr, 'b.c.')).toEqual([undefined, undefined, undefined]);
});
});
13 changes: 13 additions & 0 deletions src/app/pipes/array/pluck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {PipeTransform, Pipe, Injectable} from '@angular/core';
import {extractProperty} from '../utils/utils';

@Injectable()
@Pipe({name: 'pluck'})
export class PluckPipe implements PipeTransform {

transform(arr: any[], map: string): any[] {
return Array.isArray(arr)
? arr.map(e => extractProperty(e, map))
: arr;
}
}
15 changes: 15 additions & 0 deletions src/app/pipes/array/shuffle.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {ShufflePipe} from './shuffle';

describe('ShufflePipe', () => {
let pipe: ShufflePipe;

beforeEach(() => {
pipe = new ShufflePipe();
});

it('should return shuffled array', () => {
expect(pipe.transform([42])).toEqual([42]);
expect(pipe.transform(['foo'])).toEqual(['foo']);
expect(pipe.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).length).toEqual(10);
});
});
23 changes: 23 additions & 0 deletions src/app/pipes/array/shuffle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {PipeTransform, Pipe, Injectable} from '@angular/core';
import {extractProperty} from '../utils/utils';

@Injectable()
@Pipe({name: 'shuffle'})
export class ShufflePipe implements PipeTransform {

// Using a version of the Fisher-Yates shuffle algorithm
// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
transform(arr: any[]): any[] {
if (!Array.isArray(arr)) {
return arr;
}

let shuffled = Array.from(arr);
for (let i = 0, n = arr.length - 1, l = n - 1; i < l; ++i) {
const j = Math.floor(Math.random() * (n - i + 1)) + i;
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}

return shuffled;
}
}
19 changes: 19 additions & 0 deletions src/app/pipes/array/some.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {SomePipe} from './some';
import {isNumber, isUndefined} from '../utils/utils';

describe('SomePipe', () => {
let pipe: SomePipe;

beforeEach(() => {
pipe = new SomePipe();
});

it('should check if some elements of the array fits the predicate', () => {
expect(pipe.transform([1, 2, 3, 4], isNumber)).toBeTruthy();
expect(pipe.transform([1, 2, 3, 'a'], isNumber)).toBeTruthy();
expect(pipe.transform([null, undefined, 'a', {}, []], isNumber)).toBeFalsy();
expect(pipe.transform([1, 2, 3, 4], isUndefined)).toBeFalsy();
expect(pipe.transform([undefined, undefined, 1], isUndefined)).toBeTruthy();
expect(pipe.transform([undefined, undefined], isUndefined)).toBeTruthy();
});
});
11 changes: 11 additions & 0 deletions src/app/pipes/array/some.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {PipeTransform, Pipe, Injectable} from '@angular/core';
import {extractProperty} from '../utils/utils';

@Injectable()
@Pipe({name: 'some'})
export class SomePipe implements PipeTransform {

transform(arr: any[], predicate: (value: any, index: number, array: any[]) => boolean): boolean {
return Array.isArray(arr) ? arr.some(predicate) : arr;
}
}
34 changes: 34 additions & 0 deletions src/app/pipes/utils/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {extractProperty} from './utils';

describe('Utils Tests', () => {

it('should extract properties properly', () => {
const obj = {
a: 1,
b: {
c: 2,
d: {
e: 3
}
},
f: {
g: 4,
h: 5,
i: {
j: {
k: {
l: 6
}
}
}
}
};

expect(extractProperty(obj, 'a')).toEqual(1);
expect(extractProperty(obj, 'b.c')).toEqual(2);
expect(extractProperty(obj, 'b.d.e')).toEqual(3);
expect(extractProperty(obj, 'f.g')).toEqual(4);
expect(extractProperty(obj, 'f.i.j.k.l')).toEqual(6);
expect(extractProperty(obj, 'f.i.j.k.l.')).toEqual(undefined);
});
});
Loading

0 comments on commit e33f5e6

Please sign in to comment.